diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index dcbf086f39208..bdf14bf19ae84 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: 2022-09-20 +date: 2022-09-21 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 99d010dcd47bb..1dbd552804863 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index fb6b6937fc76b..16ee88902efc4 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 70b1838415a1c..3a59a9f336d06 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index b0e9d5757bffd..1ad2876e6274d 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -196,7 +196,7 @@ "APMPluginSetupDependencies", ") => { config$: ", "Observable", - "; autoCreateApmDataView: boolean; serviceMapEnabled: boolean; serviceMapFingerprintBucketSize: number; serviceMapTraceIdBucketSize: number; serviceMapFingerprintGlobalBucketSize: number; serviceMapTraceIdGlobalBucketSize: number; serviceMapMaxTracesPerRequest: number; ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; searchAggregatedTransactions: ", + "; autoCreateApmDataView: boolean; serviceMapEnabled: boolean; serviceMapFingerprintBucketSize: number; serviceMapTraceIdBucketSize: number; serviceMapFingerprintGlobalBucketSize: number; serviceMapTraceIdGlobalBucketSize: number; serviceMapMaxTracesPerRequest: number; ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; searchAggregatedServiceMetrics: boolean; searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", "; telemetryCollectionEnabled: boolean; metricsInterval: number; agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; }>>; getApmIndices: () => Promise<", "ApmIndicesConfig", @@ -415,7 +415,7 @@ "label": "config", "description": [], "signature": [ - "{ readonly indices: Readonly<{} & { metric: string; error: string; span: string; transaction: string; sourcemap: string; onboarding: string; }>; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; readonly searchAggregatedTransactions: ", + "{ readonly indices: Readonly<{} & { metric: string; error: string; span: string; transaction: string; sourcemap: string; onboarding: string; }>; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; readonly searchAggregatedServiceMetrics: boolean; readonly searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", "; readonly telemetryCollectionEnabled: boolean; readonly metricsInterval: number; readonly agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; }" ], @@ -781,7 +781,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\" | \"GET /internal/apm/settings/labs\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/service_groups/services_count\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\" | \"GET /internal/apm/settings/labs\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -811,7 +811,7 @@ "label": "APMConfig", "description": [], "signature": [ - "{ readonly indices: Readonly<{} & { metric: string; error: string; span: string; transaction: string; sourcemap: string; onboarding: string; }>; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; readonly searchAggregatedTransactions: ", + "{ readonly indices: Readonly<{} & { metric: string; error: string; span: string; transaction: string; sourcemap: string; onboarding: string; }>; readonly autoCreateApmDataView: boolean; readonly serviceMapEnabled: boolean; readonly serviceMapFingerprintBucketSize: number; readonly serviceMapTraceIdBucketSize: number; readonly serviceMapFingerprintGlobalBucketSize: number; readonly serviceMapTraceIdGlobalBucketSize: number; readonly serviceMapMaxTracesPerRequest: number; readonly ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; readonly searchAggregatedServiceMetrics: boolean; readonly searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", "; readonly telemetryCollectionEnabled: boolean; readonly metricsInterval: number; readonly agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; }" ], @@ -3881,6 +3881,26 @@ }, ", { terms: string[]; }, ", "APMRouteCreateOptions", + ">; \"GET /internal/apm/service_groups/services_count\": ", + "ServerRoute", + "<\"GET /internal/apm/service_groups/services_count\", ", + "TypeC", + "<{ query: ", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>; }>, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { servicesCounts: Record; }, ", + "APMRouteCreateOptions", ">; \"GET /internal/apm/service-group/services\": ", "ServerRoute", "<\"GET /internal/apm/service-group/services\", ", @@ -3932,18 +3952,14 @@ "<\"POST /internal/apm/service-group\", ", "TypeC", "<{ query: ", - "IntersectionC", + "UnionC", "<[", - "TypeC", - "<{ start: ", - "Type", - "; end: ", - "Type", - "; }>, ", "PartialC", "<{ serviceGroupId: ", "StringC", - "; }>]>; body: ", + "; }>, ", + "UndefinedC", + "]>; body: ", "TypeC", "<{ groupName: ", "StringC", @@ -5091,11 +5107,9 @@ "section": "def-server.APMRouteHandlerResources", "text": "APMRouteHandlerResources" }, - ", { charts: { title: string; key: string; yUnit: ", - "YUnit", - "; series: { title: string; key: string; type: ", - "ChartType", - "; color: string; overallValue: number; data: { x: number; y: number | null; }[]; }[]; }[]; }, ", + ", { charts: ", + "FetchAndTransformMetrics", + "[]; }, ", "APMRouteCreateOptions", ">; \"POST /internal/apm/latency/overall_distribution/transactions\": ", "ServerRoute", @@ -5604,7 +5618,7 @@ "description": [], "signature": [ "Observable", - "; autoCreateApmDataView: boolean; serviceMapEnabled: boolean; serviceMapFingerprintBucketSize: number; serviceMapTraceIdBucketSize: number; serviceMapFingerprintGlobalBucketSize: number; serviceMapTraceIdGlobalBucketSize: number; serviceMapMaxTracesPerRequest: number; ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; searchAggregatedTransactions: ", + "; autoCreateApmDataView: boolean; serviceMapEnabled: boolean; serviceMapFingerprintBucketSize: number; serviceMapTraceIdBucketSize: number; serviceMapFingerprintGlobalBucketSize: number; serviceMapTraceIdGlobalBucketSize: number; serviceMapMaxTracesPerRequest: number; ui: Readonly<{} & { enabled: boolean; transactionGroupBucketSize: number; maxTraceItems: number; }>; searchAggregatedServiceMetrics: boolean; searchAggregatedTransactions: ", "SearchAggregatedTransactionSetting", "; telemetryCollectionEnabled: boolean; metricsInterval: number; agent: Readonly<{} & { migrations: Readonly<{} & { enabled: boolean; }>; }>; }>>" ], diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 4e665c7bfea03..936fb386563a2 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; @@ -21,7 +21,7 @@ Contact [APM UI](https://github.com/orgs/elastic/teams/apm-ui) for questions reg | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 38 | 0 | 38 | 52 | +| 38 | 0 | 38 | 51 | ## Client diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index dcb08b6198153..9f93e0cf30bad 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index dce7e1d14c5ca..03ef60650c287 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 46a35412e6ae1..e1070b82be030 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: 2022-09-20 +date: 2022-09-21 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 a6ee546714ecf..9c1f56437d048 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: 2022-09-20 +date: 2022-09-21 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 b62a72791c792..496b2c6c79551 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: 2022-09-20 +date: 2022-09-21 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 d88f07961f1e9..58a63e62dd73a 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_experiments.devdocs.json b/api_docs/cloud_experiments.devdocs.json new file mode 100644 index 0000000000000..0f827e35ec52a --- /dev/null +++ b/api_docs/cloud_experiments.devdocs.json @@ -0,0 +1,370 @@ +{ + "id": "cloudExperiments", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsMetric", + "type": "Interface", + "tags": [], + "label": "CloudExperimentsMetric", + "description": [ + "\nDefinition of the metric to report back to the A/B testing service to measure the conversions.\n" + ], + "signature": [ + { + "pluginId": "cloudExperiments", + "scope": "common", + "docId": "kibCloudExperimentsPluginApi", + "section": "def-common.CloudExperimentsMetric", + "text": "CloudExperimentsMetric" + }, + "" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsMetric.name", + "type": "Uncategorized", + "tags": [], + "label": "name", + "description": [ + "\nThe name of the metric {@link CloudExperimentsMetricNames}" + ], + "signature": [ + "never" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsMetric.meta", + "type": "Uncategorized", + "tags": [], + "label": "meta", + "description": [ + "\nAny optional data to enrich the context of the metric. Or if the conversion is based on a non-numeric value." + ], + "signature": [ + "Data | undefined" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsMetric.value", + "type": "number", + "tags": [], + "label": "value", + "description": [ + "\nThe numeric value of the metric. Bear in mind that they are averaged by the underlying solution.\nTypical values to report here are time-to-action, number of panels in a loaded dashboard, and page load time." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginSetup", + "type": "Interface", + "tags": [], + "label": "CloudExperimentsPluginSetup", + "description": [ + "\nThe contract of the setup lifecycle method.\n" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginSetup.identifyUser", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "identifyUser", + "description": [ + "\nIdentifies the user in the A/B testing service.\nFor now, we only rely on the user ID. In the future, we may request further details for more targeted experiments." + ], + "signature": [ + "(userId: string, userMetadata?: Record | undefined) => void" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/public/plugin.tsx" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/server/plugin.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/public/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/public/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/public/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/public/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/server/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/server/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/server/plugin.test.ts" + }, + { + "plugin": "cloud", + "path": "x-pack/plugins/cloud/server/plugin.test.ts" + } + ], + "children": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginSetup.identifyUser.$1", + "type": "string", + "tags": [], + "label": "userId", + "description": [ + "The unique identifier of the user in the experiment." + ], + "signature": [ + "string" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginSetup.identifyUser.$2", + "type": "Object", + "tags": [], + "label": "userMetadata", + "description": [ + "Additional attributes to the user. Take care to ensure these values do not contain PII." + ], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginStart", + "type": "Interface", + "tags": [], + "label": "CloudExperimentsPluginStart", + "description": [ + "\nThe contract of the start lifecycle method\n" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginStart.getVariation", + "type": "Function", + "tags": [], + "label": "getVariation", + "description": [ + "\nFetch the configuration assigned to variation `configKey`. If nothing is found, fallback to `defaultValue`." + ], + "signature": [ + "(featureFlagName: \"security-solutions.add-integrations-url\", defaultValue: Data) => Promise" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginStart.getVariation.$1", + "type": "string", + "tags": [], + "label": "featureFlagName", + "description": [ + "The name of the key to find the config variation. {@link CloudExperimentsFeatureFlagNames }." + ], + "signature": [ + "\"security-solutions.add-integrations-url\"" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginStart.getVariation.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultValue", + "description": [ + "The fallback value in case no variation is found." + ], + "signature": [ + "Data" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginStart.reportMetric", + "type": "Function", + "tags": [], + "label": "reportMetric", + "description": [ + "\nReport metrics back to the A/B testing service to measure the conversion rate for each variation in the experiment." + ], + "signature": [ + "(metric: ", + { + "pluginId": "cloudExperiments", + "scope": "common", + "docId": "kibCloudExperimentsPluginApi", + "section": "def-common.CloudExperimentsMetric", + "text": "CloudExperimentsMetric" + }, + ") => void" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsPluginStart.reportMetric.$1", + "type": "Object", + "tags": [], + "label": "metric", + "description": [ + "{@link CloudExperimentsMetric }" + ], + "signature": [ + { + "pluginId": "cloudExperiments", + "scope": "common", + "docId": "kibCloudExperimentsPluginApi", + "section": "def-common.CloudExperimentsMetric", + "text": "CloudExperimentsMetric" + }, + "" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsFeatureFlagNames", + "type": "Type", + "tags": [], + "label": "CloudExperimentsFeatureFlagNames", + "description": [ + "\nThe names of the feature flags declared in Kibana.\nValid keys are defined in {@link FEATURE_FLAG_NAMES}. When using a new feature flag, add the name to the list.\n" + ], + "signature": [ + "\"security-solutions.add-integrations-url\"" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "cloudExperiments", + "id": "def-common.CloudExperimentsMetricNames", + "type": "Type", + "tags": [], + "label": "CloudExperimentsMetricNames", + "description": [ + "\nThe names of the metrics declared in Kibana.\nValid keys are defined in {@link METRIC_NAMES}. When reporting a new metric, add the name to the list.\n" + ], + "signature": [ + "never" + ], + "path": "x-pack/plugins/cloud_integrations/cloud_experiments/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx new file mode 100644 index 0000000000000..f80478c49dede --- /dev/null +++ b/api_docs/cloud_experiments.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: kibCloudExperimentsPluginApi +slug: /kibana-dev-docs/api/cloudExperiments +title: "cloudExperiments" +image: https://source.unsplash.com/400x175/?github +description: API docs for the cloudExperiments plugin +date: 2022-09-21 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] +--- +import cloudExperimentsObj from './cloud_experiments.devdocs.json'; + +Provides the necessary APIs to implement A/B testing scenarios, fetching the variations in configuration and reporting back metrics to track conversion rates of the experiments. + +Contact [Kibana Core](https://github.com/orgs/elastic/teams/@elastic/kibana-core) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 16 | 0 | 0 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index beeef9814456f..8e2501623ac24 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: 2022-09-20 +date: 2022-09-21 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 266884e1d4607..5d4888478dedf 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 6e0b9d0ebebfd..51aa262c87e5a 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index dd0a8f399f350..ce4999200ef16 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -11219,6 +11219,14 @@ "plugin": "graph", "path": "x-pack/plugins/graph/public/helpers/saved_workspace_utils.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts" + }, { "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/saved_object.test.ts" @@ -11899,6 +11907,69 @@ ], "returnComment": [] }, + { + "parentPluginId": "core", + "id": "def-public.SavedObjectsClientContract.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nDeletes multiple documents at once" + ], + "signature": [ + "(objects: ", + "SavedObjectTypeIdTuple", + "[], options?: ", + "SavedObjectsBulkDeleteOptions", + " | undefined) => Promise<", + "SavedObjectsBulkDeleteResponse", + ">" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-browser/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-public.SavedObjectsClientContract.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [ + "- an array of objects containing id, type" + ], + "signature": [ + "SavedObjectTypeIdTuple", + "[]" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-browser/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "core", + "id": "def-public.SavedObjectsClientContract.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "- optional force argument to force deletion of objects in a namespace other than the scoped client" + ], + "signature": [ + "SavedObjectsBulkDeleteOptions", + " | undefined" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-browser/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "The bulk delete result for the saved objects for the given types and ids." + ] + }, { "parentPluginId": "core", "id": "def-public.SavedObjectsClientContract.find", @@ -15423,7 +15494,7 @@ "signature": [ "Pick<", "Toast", - ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\"> & { title?: string | ", + ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\" | \"css\"> & { title?: string | ", "MountPoint", " | undefined; text?: string | ", "MountPoint", @@ -15464,7 +15535,7 @@ "signature": [ "Pick<", "Toast", - ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\"> & { title?: string | ", + ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\" | \"css\"> & { title?: string | ", "MountPoint", " | undefined; text?: string | ", "MountPoint", @@ -17831,6 +17902,63 @@ ], "returnComment": [] }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsRepository.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\n {@inheritDoc ISavedObjectsRepository.bulkDelete}" + ], + "signature": [ + "(objects: ", + "SavedObjectsBulkDeleteObject", + "[], options?: ", + "SavedObjectsBulkDeleteOptions", + " | undefined) => Promise<", + "SavedObjectsBulkDeleteResponse", + ">" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server-internal/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsRepository.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteObject", + "[]" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server-internal/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsRepository.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteOptions", + " | undefined" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server-internal/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "core", "id": "def-server.SavedObjectsRepository.deleteByNamespace", @@ -22645,6 +22773,104 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.total", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.total'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.default.total", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.default.total'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.custom.total", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.custom.total'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "node_modules/@types/kbn__core-usage-data-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "core", "id": "def-server.CoreUsageStats.apiCalls.savedObjectsCreate.total", @@ -30442,6 +30668,67 @@ ], "returnComment": [] }, + { + "parentPluginId": "core", + "id": "def-server.ISavedObjectsRepository.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nDeletes multiple documents at once" + ], + "signature": [ + "(objects: ", + "SavedObjectsBulkDeleteObject", + "[], options?: ", + "SavedObjectsBulkDeleteOptions", + " | undefined) => Promise<", + "SavedObjectsBulkDeleteResponse", + ">" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.ISavedObjectsRepository.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [ + "- an array of objects containing id and type" + ], + "signature": [ + "SavedObjectsBulkDeleteObject", + "[]" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "core", + "id": "def-server.ISavedObjectsRepository.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteOptions", + " | undefined" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "- { statuses: [{ id, type, success, error: { message } }] }" + ] + }, { "parentPluginId": "core", "id": "def-server.ISavedObjectsRepository.deleteByNamespace", @@ -40565,6 +40852,14 @@ "plugin": "graph", "path": "x-pack/plugins/graph/public/helpers/saved_workspace_utils.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts" + }, { "plugin": "savedObjects", "path": "src/plugins/saved_objects/public/saved_object/saved_object.test.ts" @@ -41252,6 +41547,131 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteObject", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteObject", + "description": [ + "\n" + ], + "signature": [ + "SavedObjectsBulkDeleteObject" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteObject.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteObject.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteOptions", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteOptions", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteOptions", + " extends ", + "SavedObjectsBaseOptions" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteOptions.refresh", + "type": "CompoundType", + "tags": [], + "label": "refresh", + "description": [ + "The Elasticsearch Refresh setting for this operation" + ], + "signature": [ + "MutatingOperationRefreshSetting", + " | undefined" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteOptions.force", + "type": "CompoundType", + "tags": [], + "label": "force", + "description": [ + "\nForce deletion of all objects that exists in multiple namespaces, applied to all objects." + ], + "signature": [ + "boolean | undefined" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteResponse", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteResponse", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteResponse" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsBulkDeleteResponse.statuses", + "type": "Array", + "tags": [], + "label": "statuses", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteStatus", + "[]" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "core", "id": "def-server.SavedObjectsBulkGetObject", @@ -41931,6 +42351,63 @@ ], "returnComment": [] }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsClientContract.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nDeletes multiple SavedObjects batched together as a single request\n" + ], + "signature": [ + "(objects: ", + "SavedObjectsBulkDeleteObject", + "[], options?: ", + "SavedObjectsBulkDeleteOptions", + " | undefined) => Promise<", + "SavedObjectsBulkDeleteResponse", + ">" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsClientContract.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteObject", + "[]" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "core", + "id": "def-server.SavedObjectsClientContract.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteOptions", + " | undefined" + ], + "path": "node_modules/@types/kbn__core-saved-objects-api-server/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "core", "id": "def-server.SavedObjectsClientContract.find", diff --git a/api_docs/core.mdx b/api_docs/core.mdx index ccf426c9b6909..a5cd7b55e96a4 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2657 | 0 | 45 | 2 | +| 2684 | 0 | 45 | 0 | ## Client diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 6407c53bc8db9..cc8febab951ca 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: 2022-09-20 +date: 2022-09-21 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 53da1adcb0d6e..a1e2f06b410e5 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: 2022-09-20 +date: 2022-09-21 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 d39b30e5de370..ed8980fc7c838 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: 2022-09-20 +date: 2022-09-21 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 5c4d12a6cb3d5..cb7c49f026491 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 09c1081a7ca5a..dfc44a7ebf77d 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: 2022-09-20 +date: 2022-09-21 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 3c16e2d5fedae..fa49792d2181c 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 21f01d16fd2a4..15d7ddfaff816 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: 2022-09-20 +date: 2022-09-21 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 cbfd433f1a095..cd3ddbce16f08 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: 2022-09-20 +date: 2022-09-21 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 b47e57d899dc9..706182af7954b 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index 0ba596a1b00b6..9394b62cc1a9c 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -17409,7 +17409,7 @@ "signature": [ "Pick<", "Toast", - ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\"> & { title?: string | ", + ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\" | \"css\"> & { title?: string | ", "MountPoint", " | undefined; text?: string | ", "MountPoint", @@ -21334,7 +21334,7 @@ "signature": [ "Pick<", "Toast", - ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\"> & { title?: string | ", + ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\" | \"css\"> & { title?: string | ", "MountPoint", " | undefined; text?: string | ", "MountPoint", diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index cea8ef1557292..95d0e05ecf2ab 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: 2022-09-20 +date: 2022-09-21 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 e415597a7fcb6..73e19b646e6f6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 2ca8394737f06..26c1133aa166d 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -43,7 +43,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | | | visTypeTimeseries, graph, dataViewManagement | - | -| | lens, observability, dataVisualizer, fleet, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | +| | observability, dataVisualizer, fleet, cloudSecurityPosture, discoverEnhanced, osquery, synthetics | - | | | dataViewManagement, dataViews | - | | | dataViews, dataViewManagement | - | | | dataViewManagement, dataViews | - | @@ -62,13 +62,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | canvas | - | | | canvas | - | | | canvas | - | +| | cloud | - | | | spaces, savedObjectsManagement | - | | | spaces, savedObjectsManagement | - | | | actions, ml, savedObjectsTagging, enterpriseSearch | - | | | enterpriseSearch | - | | | console, @kbn/core-elasticsearch-server-internal | - | | | spaces, security, alerting | 8.8.0 | -| | spaces, security, actions, alerting, ml, remoteClusters, graph, indexLifecycleManagement, mapsEms, painlessLab, rollup, searchprofiler, snapshotRestore, transform, upgradeAssistant | 8.8.0 | +| | spaces, security, actions, alerting, ml, remoteClusters, graph, indexLifecycleManagement, mapsEms, painlessLab, rollup, searchprofiler, securitySolution, snapshotRestore, transform, upgradeAssistant | 8.8.0 | | | embeddable, discover, presentationUtil, dashboard, graph | 8.8.0 | | | apm, security, securitySolution | 8.8.0 | | | apm, security, securitySolution | 8.8.0 | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 2d9fa24ea5276..33ca134222c20 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -178,6 +178,7 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/public/plugin.tsx#:~:text=environment) | 8.8.0 | +| | [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/public/plugin.tsx#:~:text=identifyUser), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/server/plugin.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/public/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/public/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/public/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/public/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/server/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/server/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/server/plugin.test.ts#:~:text=identifyUser), [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/server/plugin.test.ts#:~:text=identifyUser) | - | | | [chat.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cloud/server/routes/chat.ts#:~:text=authc) | - | @@ -430,7 +431,6 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=indexPatternId) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave) | 8.8.0 | @@ -655,11 +655,12 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | +| | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | | | [request_context_factory.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=authc), [request_context_factory.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=authc), [create_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts#:~:text=authc), [delete_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts#:~:text=authc), [finalize_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts#:~:text=authc), [open_close_signals_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts#:~:text=authc), [preview_rules_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts#:~:text=authc), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/timeline/utils/common.ts#:~:text=authc) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/index.tsx#:~:text=onAppLeave), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/plugin.tsx#:~:text=onAppLeave) | 8.8.0 | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/types.ts#:~:text=AppLeaveHandler), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/types.ts#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler) | 8.8.0 | -| | [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes) | - | -| | [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes) | - | +| | [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts#:~:text=SavedObjectAttributes), [saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts#:~:text=SavedObjectAttributes) | - | +| | [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_types.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [legacy_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions/legacy_migrations.ts#:~:text=SavedObjectAttributes), [saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts#:~:text=SavedObjectAttributes), [saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/risk_score/containers/onboarding/api/saved_objects.ts#:~:text=SavedObjectAttributes) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 6275c5e9b7f53..a7dc1bdec8678 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -167,6 +167,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | --------|-------|-----------|-----------| | securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | | securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | +| securitySolution | | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | | securitySolution | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/index.tsx#:~:text=onAppLeave), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/plugin.tsx#:~:text=onAppLeave) | 8.8.0 | | securitySolution | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/types.ts#:~:text=AppLeaveHandler), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/types.ts#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler) | 8.8.0 | @@ -193,5 +194,5 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Plugin | Deprecated API | Reference location(s) | Remove By | | --------|-------|-----------|-----------| -| lens | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave), [visualize_top_nav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx#:~:text=onAppLeave), [visualize_editor_common.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_editor_common.tsx#:~:text=onAppLeave), [app.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/app.tsx#:~:text=onAppLeave), [index.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/index.tsx#:~:text=onAppLeave) | 8.8.0 | -| management | | [application.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/management/public/application.tsx#:~:text=appBasePath) | 8.8.0 | \ No newline at end of file +| management | | [application.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/management/public/application.tsx#:~:text=appBasePath) | 8.8.0 | +| visualizations | | [visualize_top_nav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx#:~:text=onAppLeave), [visualize_editor_common.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_editor_common.tsx#:~:text=onAppLeave), [app.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/app.tsx#:~:text=onAppLeave), [index.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/index.tsx#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave) | 8.8.0 | \ No newline at end of file diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index f43e7dccfe704..08b245fb26f43 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index c9ebfdee37434..695319775e984 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -312,10 +312,6 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "lens", - "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" - }, { "plugin": "observability", "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx" @@ -362,6 +358,27 @@ } ] }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverAppLocatorParams.dataViewSpec", + "type": "Object", + "tags": [], + "label": "dataViewSpec", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + " | undefined" + ], + "path": "src/plugins/discover/public/locator.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "discover", "id": "def-public.DiscoverAppLocatorParams.timeRange", diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index d0066edd11e12..22482b37187c2 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 96 | 0 | 79 | 4 | +| 97 | 0 | 80 | 4 | ## Client diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 7b8b8601af087..e29728560aab4 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index d938439ede797..2f5fbce453b35 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: 2022-09-20 +date: 2022-09-21 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 bf199f204fba2..57604fa09d9cc 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: 2022-09-20 +date: 2022-09-21 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 19aca55bed367..10e8ab28d577a 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: 2022-09-20 +date: 2022-09-21 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 a7d4bd56a4065..d21f75ff234d8 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 24b08955cb1ab..799b9e84cc1fd 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.devdocs.json b/api_docs/event_annotation.devdocs.json index 35e2988d5b946..0bf1025c1dd96 100644 --- a/api_docs/event_annotation.devdocs.json +++ b/api_docs/event_annotation.devdocs.json @@ -607,7 +607,7 @@ "label": "AvailableAnnotationIcon", "description": [], "signature": [ - "\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"tag\" | \"triangle\"" + "\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"starFilled\" | \"tag\" | \"triangle\"" ], "path": "src/plugins/event_annotation/common/types.ts", "deprecated": false, @@ -1361,7 +1361,7 @@ "label": "options", "description": [], "signature": [ - "(\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"tag\" | \"triangle\")[]" + "(\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"starFilled\" | \"tag\" | \"triangle\")[]" ], "path": "src/plugins/event_annotation/common/manual_event_annotation/index.ts", "deprecated": false, @@ -2471,7 +2471,7 @@ "label": "options", "description": [], "signature": [ - "(\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"tag\" | \"triangle\")[]" + "(\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"starFilled\" | \"tag\" | \"triangle\")[]" ], "path": "src/plugins/event_annotation/common/query_point_event_annotation/index.ts", "deprecated": false, diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index d5e087678a1d0..b856ac4924147 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index d730f68e18eab..12011c049c6f6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index a3ee129f44d7a..04fb06c8c96d4 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: 2022-09-20 +date: 2022-09-21 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 3b708aa6953ee..d0b10885cf2b7 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: 2022-09-20 +date: 2022-09-21 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 3a813a40fc8f4..de91bc5178131 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: 2022-09-20 +date: 2022-09-21 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 9c315a54f4499..1cc9d08db5a90 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: 2022-09-20 +date: 2022-09-21 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 b821534dec8b8..9fcf50bff28ef 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: 2022-09-20 +date: 2022-09-21 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 45ed0cf31366f..bc16b14f88d03 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: 2022-09-20 +date: 2022-09-21 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 c9463ec11ba52..7b72a487826e6 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: 2022-09-20 +date: 2022-09-21 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 1518c761b6a23..c219691750f84 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: 2022-09-20 +date: 2022-09-21 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 0f12cfcfe0367..6929d4d65ff1c 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: 2022-09-20 +date: 2022-09-21 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 74cf96e0e3b2c..cf8447fa6e554 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: 2022-09-20 +date: 2022-09-21 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 2897faff88580..b86adf33d39e5 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: 2022-09-20 +date: 2022-09-21 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 c4dd54fe09f32..3fe265b6ba374 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.devdocs.json b/api_docs/expression_x_y.devdocs.json index 46ce5d448b1e5..70749833d4563 100644 --- a/api_docs/expression_x_y.devdocs.json +++ b/api_docs/expression_x_y.devdocs.json @@ -1939,7 +1939,7 @@ "label": "AvailableReferenceLineIcon", "description": [], "signature": [ - "\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"tag\" | \"triangle\" | \"empty\"" + "\"circle\" | \"asterisk\" | \"alert\" | \"bell\" | \"bolt\" | \"bug\" | \"editorComment\" | \"flag\" | \"heart\" | \"mapMarker\" | \"pinFilled\" | \"starEmpty\" | \"starFilled\" | \"tag\" | \"triangle\" | \"empty\"" ], "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts", "deprecated": false, diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index d94ee04294bb3..c017cb7f59f51 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: 2022-09-20 +date: 2022-09-21 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 3d4b511820a01..8bd22f5dbc372 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: 2022-09-20 +date: 2022-09-21 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 4589136f7b707..fb97fac6d9a73 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: 2022-09-20 +date: 2022-09-21 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 0583d1db89a25..02113ea2e591b 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 260869a64bd85..3a28e7c492bf3 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: 2022-09-20 +date: 2022-09-21 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 98d50b6c79efc..bb3bd2bbcff56 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 24e0f4dce933a..66f288b6ca432 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -5690,6 +5690,167 @@ ], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate", + "type": "Function", + "tags": [], + "label": "bulkUpdate", + "description": [], + "signature": [ + "(soClient: ", + "SavedObjectsClientContract", + ", esClient: ", + "ElasticsearchClient", + ", packagePolicyUpdates: (", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.NewPackagePolicy", + "text": "NewPackagePolicy" + }, + " & { version?: string | undefined; id: string; })[], options?: { user?: ", + { + "pluginId": "security", + "scope": "common", + "docId": "kibSecurityPluginApi", + "section": "def-common.AuthenticatedUser", + "text": "AuthenticatedUser" + }, + " | undefined; force?: boolean | undefined; } | undefined, currentVersion?: string | undefined) => Promise<", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.PackagePolicy", + "text": "PackagePolicy" + }, + "[] | null>" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$1", + "type": "Object", + "tags": [], + "label": "soClient", + "description": [], + "signature": [ + "SavedObjectsClientContract" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$2", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$3", + "type": "Array", + "tags": [], + "label": "packagePolicyUpdates", + "description": [], + "signature": [ + "(", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.NewPackagePolicy", + "text": "NewPackagePolicy" + }, + " & { version?: string | undefined; id: string; })[]" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$4", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$4.user", + "type": "Object", + "tags": [], + "label": "user", + "description": [], + "signature": [ + { + "pluginId": "security", + "scope": "common", + "docId": "kibSecurityPluginApi", + "section": "def-common.AuthenticatedUser", + "text": "AuthenticatedUser" + }, + " | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$4.force", + "type": "CompoundType", + "tags": [], + "label": "force", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyClient.bulkUpdate.$5", + "type": "string", + "tags": [], + "label": "currentVersion", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-server.PackagePolicyClient.get", @@ -8856,6 +9017,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.EpmPackageAdditions.licensePath", + "type": "string", + "tags": [], + "label": "licensePath", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/epm.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.EpmPackageAdditions.keepPoliciesUpToDate", @@ -12122,6 +12297,48 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.PackageSpecConditions", + "type": "Interface", + "tags": [], + "label": "PackageSpecConditions", + "description": [], + "path": "x-pack/plugins/fleet/common/types/models/package_spec.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.PackageSpecConditions.kibana", + "type": "Object", + "tags": [], + "label": "kibana", + "description": [], + "signature": [ + "{ version: string; }" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_spec.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.PackageSpecConditions.elastic", + "type": "Object", + "tags": [], + "label": "elastic", + "description": [], + "signature": [ + "{ subscription: string; } | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_spec.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.PackageSpecIcon", @@ -12269,6 +12486,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.PackageSpecManifest.source", + "type": "Object", + "tags": [], + "label": "source", + "description": [], + "signature": [ + "{ license: string; } | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_spec.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.PackageSpecManifest.type", @@ -13827,7 +14058,7 @@ "label": "DocAssetType", "description": [], "signature": [ - "\"notice\" | \"doc\"" + "\"license\" | \"notice\" | \"doc\"" ], "path": "x-pack/plugins/fleet/common/types/models/epm.ts", "deprecated": false, @@ -14859,21 +15090,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "fleet", - "id": "def-common.PackageSpecConditions", - "type": "Type", - "tags": [], - "label": "PackageSpecConditions", - "description": [], - "signature": [ - "{ kibana: { version: string; }; }" - ], - "path": "x-pack/plugins/fleet/common/types/models/package_spec.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "fleet", "id": "def-common.PLUGIN_ID", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 398f9e82fd03a..07f8d74f9c842 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 974 | 3 | 874 | 17 | +| 986 | 3 | 886 | 17 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index c71484128ec3b..c5034da58e5a1 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index e7625a590a461..fe535e96c2df8 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: 2022-09-20 +date: 2022-09-21 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 381a739739e54..1c29739eb6bb6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index ed831349e52bd..501b570f5d017 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index c8af6660752e5..c01e2fd84fcd7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 27f5c3569fa49..8a0e939a8ed2b 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 18fb173160a21..b0b1c0aba0443 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 9056c00d72b84..32e01d93df529 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 9858dd71b40a0..376fd853d73aa 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index d20a7b9ad37dd..dc1ee35a57b69 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 091fed52214f6..b87509e3cc43f 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index adcc61574b831..0d305dac2e069 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index d946f4c837ceb..873c79fa16586 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index d39f68906c4e7..a4f4547481fd4 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index cd98524289903..382a8ad33ef27 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index fe6b3d629f334..e1eccc8fdb940 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index b5f8465d23abb..dac62dbfa13f6 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index f0bf230c94525..2f3a2e4b6e791 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index e05ed7932ea0b..948d34bfbcbd4 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 9f1463f50f008..92e27ecd44c61 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 350dfc4f21573..5901d75a22dfe 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index fe78eade4d5e8..3d141045316e9 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 1fd328a1909af..c4bf743890b27 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 36f3f627a7079..e80b8d319443f 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: 2022-09-20 +date: 2022-09-21 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 66064bc9235db..dcf4e1168cda0 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: 2022-09-20 +date: 2022-09-21 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 50c89a112f318..b0d2e856b602b 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: 2022-09-20 +date: 2022-09-21 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 946811ebef1ef..af88a7a61ecaf 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index e1e61842963b9..d179dd6f56b8d 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: 2022-09-20 +date: 2022-09-21 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 f4e1d6df66d36..610cf11db4ce2 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: 2022-09-20 +date: 2022-09-21 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 3dfe88a5fe6f8..9796cc2ef31a2 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: 2022-09-20 +date: 2022-09-21 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 770caaadc3273..be242a54c53a0 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index 88c8770f78e05..d36ee3d0a04b8 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 9985d16c3d530..92f03112a75e2 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: 2022-09-20 +date: 2022-09-21 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 8b30598c799c5..5ee4fe180b1a6 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: 2022-09-20 +date: 2022-09-21 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 7d9ba2b790cd9..ddab8a6da8ba5 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: 2022-09-20 +date: 2022-09-21 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 367e2d1efc34b..3cf2b1c781613 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: 2022-09-20 +date: 2022-09-21 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 3bc7041adc0c7..1978fd217005e 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: 2022-09-20 +date: 2022-09-21 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 04c9d11050656..f921a117aa1ac 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: 2022-09-20 +date: 2022-09-21 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 d334e274ebd27..27c1ae53f78c0 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: 2022-09-20 +date: 2022-09-21 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 fb1732696cd58..2fef5d62c1be4 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: 2022-09-20 +date: 2022-09-21 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 5841b62fe8421..fd1a6a7790662 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: 2022-09-20 +date: 2022-09-21 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 d24d2537e5a29..e323813393c86 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: 2022-09-20 +date: 2022-09-21 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 ac8c8304cbacd..8e7baa413c2d9 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: 2022-09-20 +date: 2022-09-21 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 d379d0650b330..37560d75caaa7 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: 2022-09-20 +date: 2022-09-21 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_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 1532b48e1caa7..b3de07059b8b3 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: 2022-09-20 +date: 2022-09-21 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 7ae08ec040bc7..bccffa5f3169b 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: 2022-09-20 +date: 2022-09-21 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 a46e1f96ce169..2d70af69f3207 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: 2022-09-20 +date: 2022-09-21 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 c4ade5b2f59e7..92b87e2784eb8 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: 2022-09-20 +date: 2022-09-21 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 734a7db43b735..36b71dc6bbf18 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: 2022-09-20 +date: 2022-09-21 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 b039c307cc98d..8840046d85094 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: 2022-09-20 +date: 2022-09-21 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 e53c2bfaa2f7c..d829790191100 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: 2022-09-20 +date: 2022-09-21 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 dba1d83d54bfa..ea0cddb465a58 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: 2022-09-20 +date: 2022-09-21 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 0b8ccf9d5cc52..47c38a7c769e9 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: 2022-09-20 +date: 2022-09-21 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 c9b340d67fa0e..28553cc4442de 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: 2022-09-20 +date: 2022-09-21 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 00e6556403379..e3121dd71a4c5 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: 2022-09-20 +date: 2022-09-21 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_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 8c6a0d2cc5326..51ab765a1ebfd 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: 2022-09-20 +date: 2022-09-21 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 fcf11ae9ddef9..2aca3e87366d5 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: 2022-09-20 +date: 2022-09-21 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 9c728cc39d05c..1de746416ab97 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: 2022-09-20 +date: 2022-09-21 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 57a9e5d36f00e..a8eba9d98e241 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: 2022-09-20 +date: 2022-09-21 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 579e0c95cedd1..df85327dc4356 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: 2022-09-20 +date: 2022-09-21 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 6f67e55a17c96..a90ff68ad7816 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: 2022-09-20 +date: 2022-09-21 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 9f3766a0e2e9a..8970c1fb4c739 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: 2022-09-20 +date: 2022-09-21 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 f3c49ab467f46..ca61cd3b1df6c 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: 2022-09-20 +date: 2022-09-21 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 601595113c8bd..593f2f23e1172 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: 2022-09-20 +date: 2022-09-21 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 b8dbcf387129b..1b6fc98e5aaa8 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: 2022-09-20 +date: 2022-09-21 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 d9e077756915d..58d6dab3192fc 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: 2022-09-20 +date: 2022-09-21 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 9de0e77f1d83b..bdaea106a91d2 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: 2022-09-20 +date: 2022-09-21 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 7b77b445df55e..82dfdc3bf2116 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: 2022-09-20 +date: 2022-09-21 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 226141067a8d8..53c51781010a0 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: 2022-09-20 +date: 2022-09-21 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 44deabd806282..a8b0c0db5b795 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: 2022-09-20 +date: 2022-09-21 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 4588b1e74c0fc..aa122cf8c7e6e 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: 2022-09-20 +date: 2022-09-21 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 14d84cfd0c01e..a22516bdc6e0e 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: 2022-09-20 +date: 2022-09-21 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 34101622d0bb1..a51d321654147 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: 2022-09-20 +date: 2022-09-21 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 8412cea09e8dc..458d203e20aa7 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: 2022-09-20 +date: 2022-09-21 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 a488597af297c..cc444c3d5b8ca 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: 2022-09-20 +date: 2022-09-21 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 906e6aa1e6d33..3bc9d80c72a18 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: 2022-09-20 +date: 2022-09-21 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 25cbf34eaceb0..d29a114050dbf 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: 2022-09-20 +date: 2022-09-21 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 430afd1e0013b..4509eb592b397 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: 2022-09-20 +date: 2022-09-21 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 34072ca6dfde7..af698072a94ca 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: 2022-09-20 +date: 2022-09-21 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 4d424546b14b7..eb5d40300ed87 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: 2022-09-20 +date: 2022-09-21 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 4ea933853df2d..4cff04d98dc26 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: 2022-09-20 +date: 2022-09-21 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 397f9e99b4924..721ea0c3945d9 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index c781ba9fff5a3..415f15276d937 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: 2022-09-20 +date: 2022-09-21 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 0be92db2558f6..6db848c711182 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: 2022-09-20 +date: 2022-09-21 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 06d2f6cda8dbb..573f8733da5b5 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: 2022-09-20 +date: 2022-09-21 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 1bccc28f3add7..b883779a793a0 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: 2022-09-20 +date: 2022-09-21 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 889dd33ec6144..d18c50836ba87 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: 2022-09-20 +date: 2022-09-21 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_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index d6bf834e28d3f..3d126a078dc71 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: 2022-09-20 +date: 2022-09-21 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 02de9f766f698..faa4e8f8e4e0d 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: 2022-09-20 +date: 2022-09-21 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 fd40adbec69d3..d2614fafeaf5f 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: 2022-09-20 +date: 2022-09-21 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 c7c396db97c20..9051a0bf0b52e 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: 2022-09-20 +date: 2022-09-21 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 ca70a925fbb56..c9419dbd572a9 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 3660bcc446cf5..b1dba4af85762 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: 2022-09-20 +date: 2022-09-21 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 75e85149ca6c4..b67a590ecfa75 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: 2022-09-20 +date: 2022-09-21 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 a5f96ecfd44b4..2dd6083d4293f 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: 2022-09-20 +date: 2022-09-21 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 497956f0ee8a3..ae5f69bf3d5bf 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: 2022-09-20 +date: 2022-09-21 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 24e3538122a9d..b16d6e10e8725 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: 2022-09-20 +date: 2022-09-21 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.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 58b512d1545c7..a1c0750d2f77b 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.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 de5f52b8471e4..c733e3cc061a7 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: 2022-09-20 +date: 2022-09-21 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 0637bb9d8925e..cc3c1aae43229 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: 2022-09-20 +date: 2022-09-21 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 3e7b806dc160a..f303a7a2bce56 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: 2022-09-20 +date: 2022-09-21 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_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 55eb0c12108de..500ece47590d2 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: 2022-09-20 +date: 2022-09-21 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 f50fbbca7396c..34db9ddb92aa6 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: 2022-09-20 +date: 2022-09-21 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 a674bd9826403..8736af0225f13 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: 2022-09-20 +date: 2022-09-21 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 24e800f05030e..f1ff3c7382729 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: 2022-09-20 +date: 2022-09-21 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 6d04faa001d5a..9aebf6bfe65fa 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: 2022-09-20 +date: 2022-09-21 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 67c149514411e..d9ab077872da7 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: 2022-09-20 +date: 2022-09-21 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 aae45e4a49448..bd4671af281c4 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: 2022-09-20 +date: 2022-09-21 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 99a09376c4b9b..22cc5dac4f43d 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: 2022-09-20 +date: 2022-09-21 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 fb1266aaba745..cfe0c1672a0ac 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: 2022-09-20 +date: 2022-09-21 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 b3f8467f9f307..d6f58108da44a 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: 2022-09-20 +date: 2022-09-21 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 d0b884478e8d8..5aa0b5bf3138c 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: 2022-09-20 +date: 2022-09-21 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 4374729c68ce3..59e3b1e657613 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: 2022-09-20 +date: 2022-09-21 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.devdocs.json b/api_docs/kbn_core_notifications_browser.devdocs.json index b69e0619012a3..c9bcfa0a110d8 100644 --- a/api_docs/kbn_core_notifications_browser.devdocs.json +++ b/api_docs/kbn_core_notifications_browser.devdocs.json @@ -681,7 +681,7 @@ "signature": [ "Pick<", "Toast", - ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\"> & { title?: string | ", + ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\" | \"css\"> & { title?: string | ", "MountPoint", " | undefined; text?: string | ", "MountPoint", @@ -728,7 +728,7 @@ "signature": [ "Pick<", "Toast", - ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\"> & { title?: string | ", + ", \"children\" | \"onError\" | \"hidden\" | \"color\" | \"className\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"toastLifeTimeMs\" | \"iconType\" | \"onClose\" | \"data-test-subj\" | \"css\"> & { title?: string | ", "MountPoint", " | undefined; text?: string | ", "MountPoint", diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index ed6b7c356b79f..a17faa06bcc22 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: 2022-09-20 +date: 2022-09-21 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 4e05d51b17b25..6b5aaa33c88c7 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: 2022-09-20 +date: 2022-09-21 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 0b13cdbd31306..daf8186f94e4f 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: 2022-09-20 +date: 2022-09-21 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 8f1a0f8bbbbad..7a5eff7a76390 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: 2022-09-20 +date: 2022-09-21 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 15b9282a5911d..8c8a72aa73172 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: 2022-09-20 +date: 2022-09-21 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 1e7f0b4206b89..ec24423b0c296 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: 2022-09-20 +date: 2022-09-21 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_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 7e9afcaea1185..e6385a2a75836 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: 2022-09-20 +date: 2022-09-21 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 0aea4d9e2256a..0c8abfaa31f78 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 87ef4b638ae7b..98ee357d65bf7 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: 2022-09-20 +date: 2022-09-21 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_saved_objects_api_browser.devdocs.json b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json index 2e6c45ada0542..b12a698b21606 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json @@ -248,6 +248,131 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteOptions", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteOptions", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteOptions.force", + "type": "CompoundType", + "tags": [], + "label": "force", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponse", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteResponse", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponse.statuses", + "type": "Array", + "tags": [], + "label": "statuses", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-browser", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiBrowserPluginApi", + "section": "def-common.SavedObjectsBulkDeleteResponseItem", + "text": "SavedObjectsBulkDeleteResponseItem" + }, + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponseItem", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteResponseItem", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponseItem.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponseItem.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponseItem.success", + "type": "boolean", + "tags": [], + "label": "success", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsBulkDeleteResponseItem.error", + "type": "Object", + "tags": [], + "label": "error", + "description": [], + "signature": [ + "SavedObjectError", + " | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-saved-objects-api-browser", "id": "def-common.SavedObjectsBulkResolveResponse", @@ -678,6 +803,87 @@ ], "returnComment": [] }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsClientContract.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nDeletes multiple documents at once" + ], + "signature": [ + "(objects: ", + "SavedObjectTypeIdTuple", + "[], options?: ", + { + "pluginId": "@kbn/core-saved-objects-api-browser", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiBrowserPluginApi", + "section": "def-common.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " | undefined) => Promise<", + { + "pluginId": "@kbn/core-saved-objects-api-browser", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiBrowserPluginApi", + "section": "def-common.SavedObjectsBulkDeleteResponse", + "text": "SavedObjectsBulkDeleteResponse" + }, + ">" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsClientContract.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [ + "- an array of objects containing id, type" + ], + "signature": [ + "SavedObjectTypeIdTuple", + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-browser", + "id": "def-common.SavedObjectsClientContract.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "- optional force argument to force deletion of objects in a namespace other than the scoped client" + ], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-browser", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiBrowserPluginApi", + "section": "def-common.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "The bulk delete result for the saved objects for the given types and ids." + ] + }, { "parentPluginId": "@kbn/core-saved-objects-api-browser", "id": "def-common.SavedObjectsClientContract.find", diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index fb16daa874388..a5933775d7f23 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 94 | 1 | 66 | 0 | +| 106 | 1 | 75 | 0 | ## Common diff --git a/api_docs/kbn_core_saved_objects_api_server.devdocs.json b/api_docs/kbn_core_saved_objects_api_server.devdocs.json index 74d6732ba03ba..0e040b72d2d3d 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -444,6 +444,97 @@ ], "returnComment": [] }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.ISavedObjectsRepository.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nDeletes multiple documents at once" + ], + "signature": [ + "(objects: ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteObject", + "text": "SavedObjectsBulkDeleteObject" + }, + "[], options?: ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " | undefined) => Promise<", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteResponse", + "text": "SavedObjectsBulkDeleteResponse" + }, + ">" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.ISavedObjectsRepository.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [ + "- an array of objects containing id and type" + ], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteObject", + "text": "SavedObjectsBulkDeleteObject" + }, + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.ISavedObjectsRepository.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "- { statuses: [{ id, type, success, error: { message } }] }" + ] + }, { "parentPluginId": "@kbn/core-saved-objects-api-server", "id": "def-server.ISavedObjectsRepository.deleteByNamespace", @@ -2131,6 +2222,215 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteObject", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteObject", + "description": [ + "\n" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteObject.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteObject.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteOptions", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteOptions", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " extends ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBaseOptions", + "text": "SavedObjectsBaseOptions" + } + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteOptions.refresh", + "type": "CompoundType", + "tags": [], + "label": "refresh", + "description": [ + "The Elasticsearch Refresh setting for this operation" + ], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.MutatingOperationRefreshSetting", + "text": "MutatingOperationRefreshSetting" + }, + " | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteOptions.force", + "type": "CompoundType", + "tags": [], + "label": "force", + "description": [ + "\nForce deletion of all objects that exists in multiple namespaces, applied to all objects." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteResponse", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteResponse", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteResponse.statuses", + "type": "Array", + "tags": [], + "label": "statuses", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteStatus", + "text": "SavedObjectsBulkDeleteStatus" + }, + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteStatus", + "type": "Interface", + "tags": [], + "label": "SavedObjectsBulkDeleteStatus", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteStatus.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteStatus.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteStatus.success", + "type": "boolean", + "tags": [], + "label": "success", + "description": [ + "The status of deleting the object: true for deleted, false for error" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsBulkDeleteStatus.error", + "type": "Object", + "tags": [], + "label": "error", + "description": [ + "Reason the object could not be deleted (success is false)" + ], + "signature": [ + "SavedObjectError", + " | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-saved-objects-api-server", "id": "def-server.SavedObjectsBulkGetObject", @@ -2939,6 +3239,93 @@ ], "returnComment": [] }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsClientContract.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nDeletes multiple SavedObjects batched together as a single request\n" + ], + "signature": [ + "(objects: ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteObject", + "text": "SavedObjectsBulkDeleteObject" + }, + "[], options?: ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " | undefined) => Promise<", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteResponse", + "text": "SavedObjectsBulkDeleteResponse" + }, + ">" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsClientContract.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteObject", + "text": "SavedObjectsBulkDeleteObject" + }, + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server", + "id": "def-server.SavedObjectsClientContract.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "server", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-server.SavedObjectsBulkDeleteOptions", + "text": "SavedObjectsBulkDeleteOptions" + }, + " | undefined" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, { "parentPluginId": "@kbn/core-saved-objects-api-server", "id": "def-server.SavedObjectsClientContract.find", diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index f308f99088f93..48aef5d9e3a5a 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 289 | 1 | 126 | 0 | +| 308 | 1 | 137 | 0 | ## Server diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.devdocs.json b/api_docs/kbn_core_saved_objects_api_server_internal.devdocs.json index d5a95dee2de38..79c17d6086eef 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server_internal.devdocs.json @@ -278,6 +278,62 @@ ], "returnComment": [] }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server-internal", + "id": "def-server.SavedObjectsRepository.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\n {@inheritDoc ISavedObjectsRepository.bulkDelete}" + ], + "signature": [ + "(objects: ", + "SavedObjectsBulkDeleteObject", + "[], options?: ", + "SavedObjectsBulkDeleteOptions", + ") => Promise<", + "SavedObjectsBulkDeleteResponse", + ">" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-api-server-internal", + "id": "def-server.SavedObjectsRepository.bulkDelete.$1", + "type": "Array", + "tags": [], + "label": "objects", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteObject", + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-saved-objects-api-server-internal", + "id": "def-server.SavedObjectsRepository.bulkDelete.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "SavedObjectsBulkDeleteOptions" + ], + "path": "packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "@kbn/core-saved-objects-api-server-internal", "id": "def-server.SavedObjectsRepository.deleteByNamespace", diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index f0a6438fc4fa6..8f7fe0f6163f2 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 68 | 0 | 49 | 0 | +| 71 | 0 | 51 | 0 | ## Server 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 387d4624b34cb..738cbc10225ea 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: 2022-09-20 +date: 2022-09-21 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 3fd8a5c5e9c37..d4874ff125c9d 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: 2022-09-20 +date: 2022-09-21 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 96ebbe50c9dbb..6bf81edf60447 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: 2022-09-20 +date: 2022-09-21 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 814bc13c8a0f0..f631627c7c671 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: 2022-09-20 +date: 2022-09-21 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 321a185f26b0c..f8d2a00000ad6 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: 2022-09-20 +date: 2022-09-21 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 0eff5fe3a0815..b2429c7efea6a 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 3543ac5cce759..6942d08a8a361 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: 2022-09-20 +date: 2022-09-21 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 dbb9933bd19ef..80a176a289a2b 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: 2022-09-20 +date: 2022-09-21 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 ee4489e6cee50..87fd03b5794a6 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: 2022-09-20 +date: 2022-09-21 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 f3c16660d9b57..f5c4c8c690179 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: 2022-09-20 +date: 2022-09-21 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 181a58b3b26d0..f2562939d3214 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: 2022-09-20 +date: 2022-09-21 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 9e0a46fb69b22..dca63daba9785 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: 2022-09-20 +date: 2022-09-21 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.devdocs.json b/api_docs/kbn_core_saved_objects_server_internal.devdocs.json index c4872c37e0445..5d601613ed4a7 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server_internal.devdocs.json @@ -212,6 +212,56 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-saved-objects-server-internal", + "id": "def-server.registerBulkDeleteRoute", + "type": "Function", + "tags": [], + "label": "registerBulkDeleteRoute", + "description": [], + "signature": [ + "(router: ", + "InternalSavedObjectRouter", + ", { coreUsageData }: RouteDependencies) => void" + ], + "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-server-internal", + "id": "def-server.registerBulkDeleteRoute.$1", + "type": "Object", + "tags": [], + "label": "router", + "description": [], + "signature": [ + "InternalSavedObjectRouter" + ], + "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-saved-objects-server-internal", + "id": "def-server.registerBulkDeleteRoute.$2", + "type": "Object", + "tags": [], + "label": "{ coreUsageData }", + "description": [], + "signature": [ + "RouteDependencies" + ], + "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-saved-objects-server-internal", "id": "def-server.registerBulkGetRoute", diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index a4e0fa38d323b..015215fa5039e 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 66 | 0 | 66 | 4 | +| 69 | 0 | 69 | 4 | ## Server diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 6b1a14d7b5a92..36d189e120cd8 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: 2022-09-20 +date: 2022-09-21 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 cc7cefe0fc9cc..5900ab2e01897 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 36290f4685f52..410b3389b9ef6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 764213f0fcc65..250cb345b9a21 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 5fa9cf11f74df..9e062fe408eec 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: 2022-09-20 +date: 2022-09-21 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 cd6df67e78030..448c81ec4b79a 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: 2022-09-20 +date: 2022-09-21 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 c2bbd12094c04..3593f09e53c79 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: 2022-09-20 +date: 2022-09-21 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 e8be3567313b0..c1ea683699773 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: 2022-09-20 +date: 2022-09-21 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 6bb448c563b7b..90c31ad1d6e85 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: 2022-09-20 +date: 2022-09-21 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_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index ef68d664af2c1..11ed64d22dcc7 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: 2022-09-20 +date: 2022-09-21 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 978f1833da04a..5cb8a68077a19 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: 2022-09-20 +date: 2022-09-21 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 8abf444a86f18..8b8c6e62c6fc1 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: 2022-09-20 +date: 2022-09-21 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 9ac7e4f27c121..8c4774f561e62 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: 2022-09-20 +date: 2022-09-21 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 8cdfe923481d2..729aa317ec334 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: 2022-09-20 +date: 2022-09-21 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 c82a3ba9a1c82..095a8324b79c3 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: 2022-09-20 +date: 2022-09-21 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 40f540a5048a6..bd961f3cd990a 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: 2022-09-20 +date: 2022-09-21 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 eaeeedee820f9..71f72e035cb74 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: 2022-09-20 +date: 2022-09-21 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 12ade9596f6e6..657ac74105e43 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: 2022-09-20 +date: 2022-09-21 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 931ce804b79eb..50887b10d7a0d 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.devdocs.json b/api_docs/kbn_core_usage_data_server.devdocs.json index 49517d65e5019..99ec8f759c0dd 100644 --- a/api_docs/kbn_core_usage_data_server.devdocs.json +++ b/api_docs/kbn_core_usage_data_server.devdocs.json @@ -834,6 +834,104 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.total", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.total'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.default.total", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.default.total'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.custom.total", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.custom.total'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-usage-data-server", + "id": "def-server.CoreUsageStats.apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no", + "type": "number", + "tags": [], + "label": "'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no'", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/core-usage-data-server", "id": "def-server.CoreUsageStats.apiCalls.savedObjectsCreate.total", diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 8b6294af5a33a..0c74acc01304f 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 146 | 0 | 135 | 0 | +| 153 | 0 | 142 | 0 | ## Server diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 971946e462f2f..8e592b7f85eee 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: 2022-09-20 +date: 2022-09-21 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.devdocs.json b/api_docs/kbn_core_usage_data_server_mocks.devdocs.json index 20f3ce6d5b306..0f3cc66101f7f 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.devdocs.json +++ b/api_docs/kbn_core_usage_data_server_mocks.devdocs.json @@ -83,6 +83,8 @@ "BaseIncrementOptions", "]>; incrementSavedObjectsBulkUpdate: jest.MockInstance, [options: ", "BaseIncrementOptions", + "]>; incrementSavedObjectsBulkDelete: jest.MockInstance, [options: ", + "BaseIncrementOptions", "]>; incrementSavedObjectsCreate: jest.MockInstance, [options: ", "BaseIncrementOptions", "]>; incrementSavedObjectsDelete: jest.MockInstance, [options: ", diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 0b31e5b3a34d7..f0a28f0875ed9 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: 2022-09-20 +date: 2022-09-21 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_crypto.mdx b/api_docs/kbn_crypto.mdx index 5b41d00b6b4d9..28faa9e162e77 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: 2022-09-20 +date: 2022-09-21 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 f3389cdd3d2a5..46c98951488ae 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 10bef6d0fe0ef..aa7809f7eb2e1 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 0341bd60eb0db..1843be33150fa 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: 2022-09-20 +date: 2022-09-21 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 9d36428f50b35..17b48fee7a458 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: 2022-09-20 +date: 2022-09-21 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 08ad6b9284437..5df40a7588976 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: 2022-09-20 +date: 2022-09-21 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 703febe0cd967..5340deeed61b7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index dd0d195749624..4590efe64c129 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: 2022-09-20 +date: 2022-09-21 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 2e041d294ebee..e074495e15334 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 302ca68691fea..79dcf4c12fdba 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 66d013d8f0a36..bf0588c4f99c1 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: 2022-09-20 +date: 2022-09-21 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 ab88b5be725c4..7ae016edcfb59 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: 2022-09-20 +date: 2022-09-21 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 00b04a4bbc45f..06994c389d718 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.devdocs.json b/api_docs/kbn_es_types.devdocs.json new file mode 100644 index 0000000000000..df40e62edf33b --- /dev/null +++ b/api_docs/kbn_es_types.devdocs.json @@ -0,0 +1,463 @@ +{ + "id": "@kbn/es-types", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.ESSearchOptions", + "type": "Interface", + "tags": [], + "label": "ESSearchOptions", + "description": [], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.ESSearchOptions.restTotalHitsAsInt", + "type": "boolean", + "tags": [], + "label": "restTotalHitsAsInt", + "description": [], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.AggregateOf", + "type": "Type", + "tags": [], + "label": "AggregateOf", + "description": [], + "signature": [ + "Pick & { adjacency_matrix: { buckets: ({ key: string; doc_count: number; } & SubAggregateOf)[]; }; auto_date_histogram: { interval: string; buckets: ({ key: number; key_as_string: string; doc_count: number; } & SubAggregateOf)[]; }; avg: { value: number | null; value_as_string?: string | undefined; }; avg_bucket: { value: number | null; }; boxplot: { min: number | null; max: number | null; q1: number | null; q2: number | null; q3: number | null; }; bucket_correlation: { value: number | null; }; bucket_count_ks_test: { less: number; greater: number; two_sided: number; }; bucket_script: { value: unknown; }; cardinality: { value: number; }; children: { doc_count: number; } & SubAggregateOf; composite: { after_key: CompositeKeysOf; buckets: ({ doc_count: number; key: CompositeKeysOf; } & SubAggregateOf)[]; }; cumulative_cardinality: { value: number; }; cumulative_sum: { value: number; }; date_histogram: MaybeKeyed, string>; date_range: MaybeKeyed & Partial<{ to: string | number; to_as_string: string; }> & { doc_count: number; key: string; }, string>; derivative: { value: number | null; } | undefined; extended_stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_of_squares_as_string: string; variance_population_as_string: string; variance_sampling_as_string: string; std_deviation_as_string: string; std_deviation_population_as_string: string; std_deviation_sampling_as_string: string; std_deviation_bounds_as_string: { upper: string; lower: string; upper_population: string; lower_population: string; upper_sampling: string; lower_sampling: string; }; }); extended_stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number | null; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; }; filter: { doc_count: number; } & SubAggregateOf; filters: { buckets: TAggregationContainer extends { filters: { filters: any[]; }; } ? ({ doc_count: number; } & SubAggregateOf)[] : TAggregationContainer extends { filters: { filters: Record; }; } ? { [key in keyof TAggregationContainer[\"filters\"][\"filters\"]]: { doc_count: number; } & SubAggregateOf; } & (TAggregationContainer extends { filters: { other_bucket_key: infer TOtherBucketKey; }; } ? Record> : unknown) & (TAggregationContainer extends { filters: { other_bucket: true; }; } ? { _other: { doc_count: number; } & SubAggregateOf; } : unknown) : unknown; }; geo_bounds: { top_left: { lat: number | null; lon: number | null; }; bottom_right: { lat: number | null; lon: number | null; }; }; geo_centroid: { count: number; location: { lat: number; lon: number; }; }; geo_distance: MaybeKeyed, string>; geo_hash: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; geotile_grid: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; global: { doc_count: number; } & SubAggregateOf; histogram: MaybeKeyed, string>; ip_range: MaybeKeyed; inference: { value: number; prediction_probability: number; prediction_score: number; }; max: { value: number | null; value_as_string?: string | undefined; }; max_bucket: { value: number | null; }; min: { value: number | null; value_as_string?: string | undefined; }; min_bucket: { value: number | null; }; median_absolute_deviation: { value: number | null; }; moving_avg: { value: number | null; } | undefined; moving_fn: { value: number | null; }; moving_percentiles: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record | undefined; missing: { doc_count: number; } & SubAggregateOf; multi_terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string[]; } & SubAggregateOf)[]; }; nested: { doc_count: number; } & SubAggregateOf; normalize: { value: number | null; value_as_string?: string | undefined; }; parent: { doc_count: number; } & SubAggregateOf; percentiles: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentile_ranks: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentiles_bucket: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; range: MaybeKeyed; rare_terms: ({ key: string | number; doc_count: number; } & SubAggregateOf)[]; rate: { value: number | null; }; reverse_nested: { doc_count: number; } & SubAggregateOf; random_sampler: { seed: number; probability: number; doc_count: number; } & SubAggregateOf; sampler: { doc_count: number; } & SubAggregateOf; scripted_metric: { value: unknown; }; serial_diff: { value: number | null; value_as_string?: string | undefined; }; significant_terms: { doc_count: number; bg_count: number; buckets: ({ key: string | number; score: number; doc_count: number; bg_count: number; } & SubAggregateOf)[]; }; significant_text: { doc_count: number; buckets: { key: string; doc_count: number; score: number; bg_count: number; }[]; }; stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_as_string: string; }); stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; }; string_stats: { count: number; min_length: number | null; max_length: number | null; avg_length: number | null; entropy: number | null; distribution: Record; }; sum: { value: number | null; value_as_string?: string | undefined; }; sum_bucket: { value: number | null; }; terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string | number; key_as_string?: string | undefined; } & SubAggregateOf)[]; }; top_hits: { hits: { total: { value: number; relation: \"gte\" | \"eq\"; }; max_score: number | null; hits: TAggregationContainer extends { top_hits: ", + "AggregationsTopHitsAggregation", + "; } ? HitsOf : ", + "SearchHitsMetadata", + "; }; }; top_metrics: { top: { sort: string[] | number[]; metrics: Record, string | number | null>; }[]; }; weighted_avg: { value: number | null; }; value_count: { value: number; }; }, Exclude, \"aggs\" | \"aggregations\"> & string> extends readonly any[] ? (readonly any[] & Pick & { adjacency_matrix: { buckets: ({ key: string; doc_count: number; } & SubAggregateOf)[]; }; auto_date_histogram: { interval: string; buckets: ({ key: number; key_as_string: string; doc_count: number; } & SubAggregateOf)[]; }; avg: { value: number | null; value_as_string?: string | undefined; }; avg_bucket: { value: number | null; }; boxplot: { min: number | null; max: number | null; q1: number | null; q2: number | null; q3: number | null; }; bucket_correlation: { value: number | null; }; bucket_count_ks_test: { less: number; greater: number; two_sided: number; }; bucket_script: { value: unknown; }; cardinality: { value: number; }; children: { doc_count: number; } & SubAggregateOf; composite: { after_key: CompositeKeysOf; buckets: ({ doc_count: number; key: CompositeKeysOf; } & SubAggregateOf)[]; }; cumulative_cardinality: { value: number; }; cumulative_sum: { value: number; }; date_histogram: MaybeKeyed, string>; date_range: MaybeKeyed & Partial<{ to: string | number; to_as_string: string; }> & { doc_count: number; key: string; }, string>; derivative: { value: number | null; } | undefined; extended_stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_of_squares_as_string: string; variance_population_as_string: string; variance_sampling_as_string: string; std_deviation_as_string: string; std_deviation_population_as_string: string; std_deviation_sampling_as_string: string; std_deviation_bounds_as_string: { upper: string; lower: string; upper_population: string; lower_population: string; upper_sampling: string; lower_sampling: string; }; }); extended_stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number | null; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; }; filter: { doc_count: number; } & SubAggregateOf; filters: { buckets: TAggregationContainer extends { filters: { filters: any[]; }; } ? ({ doc_count: number; } & SubAggregateOf)[] : TAggregationContainer extends { filters: { filters: Record; }; } ? { [key in keyof TAggregationContainer[\"filters\"][\"filters\"]]: { doc_count: number; } & SubAggregateOf; } & (TAggregationContainer extends { filters: { other_bucket_key: infer TOtherBucketKey; }; } ? Record> : unknown) & (TAggregationContainer extends { filters: { other_bucket: true; }; } ? { _other: { doc_count: number; } & SubAggregateOf; } : unknown) : unknown; }; geo_bounds: { top_left: { lat: number | null; lon: number | null; }; bottom_right: { lat: number | null; lon: number | null; }; }; geo_centroid: { count: number; location: { lat: number; lon: number; }; }; geo_distance: MaybeKeyed, string>; geo_hash: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; geotile_grid: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; global: { doc_count: number; } & SubAggregateOf; histogram: MaybeKeyed, string>; ip_range: MaybeKeyed; inference: { value: number; prediction_probability: number; prediction_score: number; }; max: { value: number | null; value_as_string?: string | undefined; }; max_bucket: { value: number | null; }; min: { value: number | null; value_as_string?: string | undefined; }; min_bucket: { value: number | null; }; median_absolute_deviation: { value: number | null; }; moving_avg: { value: number | null; } | undefined; moving_fn: { value: number | null; }; moving_percentiles: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record | undefined; missing: { doc_count: number; } & SubAggregateOf; multi_terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string[]; } & SubAggregateOf)[]; }; nested: { doc_count: number; } & SubAggregateOf; normalize: { value: number | null; value_as_string?: string | undefined; }; parent: { doc_count: number; } & SubAggregateOf; percentiles: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentile_ranks: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentiles_bucket: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; range: MaybeKeyed; rare_terms: ({ key: string | number; doc_count: number; } & SubAggregateOf)[]; rate: { value: number | null; }; reverse_nested: { doc_count: number; } & SubAggregateOf; random_sampler: { seed: number; probability: number; doc_count: number; } & SubAggregateOf; sampler: { doc_count: number; } & SubAggregateOf; scripted_metric: { value: unknown; }; serial_diff: { value: number | null; value_as_string?: string | undefined; }; significant_terms: { doc_count: number; bg_count: number; buckets: ({ key: string | number; score: number; doc_count: number; bg_count: number; } & SubAggregateOf)[]; }; significant_text: { doc_count: number; buckets: { key: string; doc_count: number; score: number; bg_count: number; }[]; }; stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_as_string: string; }); stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; }; string_stats: { count: number; min_length: number | null; max_length: number | null; avg_length: number | null; entropy: number | null; distribution: Record; }; sum: { value: number | null; value_as_string?: string | undefined; }; sum_bucket: { value: number | null; }; terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string | number; key_as_string?: string | undefined; } & SubAggregateOf)[]; }; top_hits: { hits: { total: { value: number; relation: \"gte\" | \"eq\"; }; max_score: number | null; hits: TAggregationContainer extends { top_hits: ", + "AggregationsTopHitsAggregation", + "; } ? HitsOf : ", + "SearchHitsMetadata", + "; }; }; top_metrics: { top: { sort: string[] | number[]; metrics: Record, string | number | null>; }[]; }; weighted_avg: { value: number | null; }; value_count: { value: number; }; }, Exclude, \"aggs\" | \"aggregations\"> & string>)[number] : Pick & { adjacency_matrix: { buckets: ({ key: string; doc_count: number; } & SubAggregateOf)[]; }; auto_date_histogram: { interval: string; buckets: ({ key: number; key_as_string: string; doc_count: number; } & SubAggregateOf)[]; }; avg: { value: number | null; value_as_string?: string | undefined; }; avg_bucket: { value: number | null; }; boxplot: { min: number | null; max: number | null; q1: number | null; q2: number | null; q3: number | null; }; bucket_correlation: { value: number | null; }; bucket_count_ks_test: { less: number; greater: number; two_sided: number; }; bucket_script: { value: unknown; }; cardinality: { value: number; }; children: { doc_count: number; } & SubAggregateOf; composite: { after_key: CompositeKeysOf; buckets: ({ doc_count: number; key: CompositeKeysOf; } & SubAggregateOf)[]; }; cumulative_cardinality: { value: number; }; cumulative_sum: { value: number; }; date_histogram: MaybeKeyed, string>; date_range: MaybeKeyed & Partial<{ to: string | number; to_as_string: string; }> & { doc_count: number; key: string; }, string>; derivative: { value: number | null; } | undefined; extended_stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_of_squares_as_string: string; variance_population_as_string: string; variance_sampling_as_string: string; std_deviation_as_string: string; std_deviation_population_as_string: string; std_deviation_sampling_as_string: string; std_deviation_bounds_as_string: { upper: string; lower: string; upper_population: string; lower_population: string; upper_sampling: string; lower_sampling: string; }; }); extended_stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number | null; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; }; filter: { doc_count: number; } & SubAggregateOf; filters: { buckets: TAggregationContainer extends { filters: { filters: any[]; }; } ? ({ doc_count: number; } & SubAggregateOf)[] : TAggregationContainer extends { filters: { filters: Record; }; } ? { [key in keyof TAggregationContainer[\"filters\"][\"filters\"]]: { doc_count: number; } & SubAggregateOf; } & (TAggregationContainer extends { filters: { other_bucket_key: infer TOtherBucketKey; }; } ? Record> : unknown) & (TAggregationContainer extends { filters: { other_bucket: true; }; } ? { _other: { doc_count: number; } & SubAggregateOf; } : unknown) : unknown; }; geo_bounds: { top_left: { lat: number | null; lon: number | null; }; bottom_right: { lat: number | null; lon: number | null; }; }; geo_centroid: { count: number; location: { lat: number; lon: number; }; }; geo_distance: MaybeKeyed, string>; geo_hash: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; geotile_grid: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; global: { doc_count: number; } & SubAggregateOf; histogram: MaybeKeyed, string>; ip_range: MaybeKeyed; inference: { value: number; prediction_probability: number; prediction_score: number; }; max: { value: number | null; value_as_string?: string | undefined; }; max_bucket: { value: number | null; }; min: { value: number | null; value_as_string?: string | undefined; }; min_bucket: { value: number | null; }; median_absolute_deviation: { value: number | null; }; moving_avg: { value: number | null; } | undefined; moving_fn: { value: number | null; }; moving_percentiles: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record | undefined; missing: { doc_count: number; } & SubAggregateOf; multi_terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string[]; } & SubAggregateOf)[]; }; nested: { doc_count: number; } & SubAggregateOf; normalize: { value: number | null; value_as_string?: string | undefined; }; parent: { doc_count: number; } & SubAggregateOf; percentiles: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentile_ranks: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentiles_bucket: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; range: MaybeKeyed; rare_terms: ({ key: string | number; doc_count: number; } & SubAggregateOf)[]; rate: { value: number | null; }; reverse_nested: { doc_count: number; } & SubAggregateOf; random_sampler: { seed: number; probability: number; doc_count: number; } & SubAggregateOf; sampler: { doc_count: number; } & SubAggregateOf; scripted_metric: { value: unknown; }; serial_diff: { value: number | null; value_as_string?: string | undefined; }; significant_terms: { doc_count: number; bg_count: number; buckets: ({ key: string | number; score: number; doc_count: number; bg_count: number; } & SubAggregateOf)[]; }; significant_text: { doc_count: number; buckets: { key: string; doc_count: number; score: number; bg_count: number; }[]; }; stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_as_string: string; }); stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; }; string_stats: { count: number; min_length: number | null; max_length: number | null; avg_length: number | null; entropy: number | null; distribution: Record; }; sum: { value: number | null; value_as_string?: string | undefined; }; sum_bucket: { value: number | null; }; terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string | number; key_as_string?: string | undefined; } & SubAggregateOf)[]; }; top_hits: { hits: { total: { value: number; relation: \"gte\" | \"eq\"; }; max_score: number | null; hits: TAggregationContainer extends { top_hits: ", + "AggregationsTopHitsAggregation", + "; } ? HitsOf : ", + "SearchHitsMetadata", + "; }; }; top_metrics: { top: { sort: string[] | number[]; metrics: Record, string | number | null>; }[]; }; weighted_avg: { value: number | null; }; value_count: { value: number; }; }, Exclude, \"aggs\" | \"aggregations\"> & string> extends ArrayLike ? (ArrayLike & Pick & { adjacency_matrix: { buckets: ({ key: string; doc_count: number; } & SubAggregateOf)[]; }; auto_date_histogram: { interval: string; buckets: ({ key: number; key_as_string: string; doc_count: number; } & SubAggregateOf)[]; }; avg: { value: number | null; value_as_string?: string | undefined; }; avg_bucket: { value: number | null; }; boxplot: { min: number | null; max: number | null; q1: number | null; q2: number | null; q3: number | null; }; bucket_correlation: { value: number | null; }; bucket_count_ks_test: { less: number; greater: number; two_sided: number; }; bucket_script: { value: unknown; }; cardinality: { value: number; }; children: { doc_count: number; } & SubAggregateOf; composite: { after_key: CompositeKeysOf; buckets: ({ doc_count: number; key: CompositeKeysOf; } & SubAggregateOf)[]; }; cumulative_cardinality: { value: number; }; cumulative_sum: { value: number; }; date_histogram: MaybeKeyed, string>; date_range: MaybeKeyed & Partial<{ to: string | number; to_as_string: string; }> & { doc_count: number; key: string; }, string>; derivative: { value: number | null; } | undefined; extended_stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_of_squares_as_string: string; variance_population_as_string: string; variance_sampling_as_string: string; std_deviation_as_string: string; std_deviation_population_as_string: string; std_deviation_sampling_as_string: string; std_deviation_bounds_as_string: { upper: string; lower: string; upper_population: string; lower_population: string; upper_sampling: string; lower_sampling: string; }; }); extended_stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number | null; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; }; filter: { doc_count: number; } & SubAggregateOf; filters: { buckets: TAggregationContainer extends { filters: { filters: any[]; }; } ? ({ doc_count: number; } & SubAggregateOf)[] : TAggregationContainer extends { filters: { filters: Record; }; } ? { [key in keyof TAggregationContainer[\"filters\"][\"filters\"]]: { doc_count: number; } & SubAggregateOf; } & (TAggregationContainer extends { filters: { other_bucket_key: infer TOtherBucketKey; }; } ? Record> : unknown) & (TAggregationContainer extends { filters: { other_bucket: true; }; } ? { _other: { doc_count: number; } & SubAggregateOf; } : unknown) : unknown; }; geo_bounds: { top_left: { lat: number | null; lon: number | null; }; bottom_right: { lat: number | null; lon: number | null; }; }; geo_centroid: { count: number; location: { lat: number; lon: number; }; }; geo_distance: MaybeKeyed, string>; geo_hash: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; geotile_grid: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; global: { doc_count: number; } & SubAggregateOf; histogram: MaybeKeyed, string>; ip_range: MaybeKeyed; inference: { value: number; prediction_probability: number; prediction_score: number; }; max: { value: number | null; value_as_string?: string | undefined; }; max_bucket: { value: number | null; }; min: { value: number | null; value_as_string?: string | undefined; }; min_bucket: { value: number | null; }; median_absolute_deviation: { value: number | null; }; moving_avg: { value: number | null; } | undefined; moving_fn: { value: number | null; }; moving_percentiles: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record | undefined; missing: { doc_count: number; } & SubAggregateOf; multi_terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string[]; } & SubAggregateOf)[]; }; nested: { doc_count: number; } & SubAggregateOf; normalize: { value: number | null; value_as_string?: string | undefined; }; parent: { doc_count: number; } & SubAggregateOf; percentiles: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentile_ranks: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentiles_bucket: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; range: MaybeKeyed; rare_terms: ({ key: string | number; doc_count: number; } & SubAggregateOf)[]; rate: { value: number | null; }; reverse_nested: { doc_count: number; } & SubAggregateOf; random_sampler: { seed: number; probability: number; doc_count: number; } & SubAggregateOf; sampler: { doc_count: number; } & SubAggregateOf; scripted_metric: { value: unknown; }; serial_diff: { value: number | null; value_as_string?: string | undefined; }; significant_terms: { doc_count: number; bg_count: number; buckets: ({ key: string | number; score: number; doc_count: number; bg_count: number; } & SubAggregateOf)[]; }; significant_text: { doc_count: number; buckets: { key: string; doc_count: number; score: number; bg_count: number; }[]; }; stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_as_string: string; }); stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; }; string_stats: { count: number; min_length: number | null; max_length: number | null; avg_length: number | null; entropy: number | null; distribution: Record; }; sum: { value: number | null; value_as_string?: string | undefined; }; sum_bucket: { value: number | null; }; terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string | number; key_as_string?: string | undefined; } & SubAggregateOf)[]; }; top_hits: { hits: { total: { value: number; relation: \"gte\" | \"eq\"; }; max_score: number | null; hits: TAggregationContainer extends { top_hits: ", + "AggregationsTopHitsAggregation", + "; } ? HitsOf : ", + "SearchHitsMetadata", + "; }; }; top_metrics: { top: { sort: string[] | number[]; metrics: Record, string | number | null>; }[]; }; weighted_avg: { value: number | null; }; value_count: { value: number; }; }, Exclude, \"aggs\" | \"aggregations\"> & string>)[number] : Pick & { adjacency_matrix: { buckets: ({ key: string; doc_count: number; } & SubAggregateOf)[]; }; auto_date_histogram: { interval: string; buckets: ({ key: number; key_as_string: string; doc_count: number; } & SubAggregateOf)[]; }; avg: { value: number | null; value_as_string?: string | undefined; }; avg_bucket: { value: number | null; }; boxplot: { min: number | null; max: number | null; q1: number | null; q2: number | null; q3: number | null; }; bucket_correlation: { value: number | null; }; bucket_count_ks_test: { less: number; greater: number; two_sided: number; }; bucket_script: { value: unknown; }; cardinality: { value: number; }; children: { doc_count: number; } & SubAggregateOf; composite: { after_key: CompositeKeysOf; buckets: ({ doc_count: number; key: CompositeKeysOf; } & SubAggregateOf)[]; }; cumulative_cardinality: { value: number; }; cumulative_sum: { value: number; }; date_histogram: MaybeKeyed, string>; date_range: MaybeKeyed & Partial<{ to: string | number; to_as_string: string; }> & { doc_count: number; key: string; }, string>; derivative: { value: number | null; } | undefined; extended_stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_of_squares_as_string: string; variance_population_as_string: string; variance_sampling_as_string: string; std_deviation_as_string: string; std_deviation_population_as_string: string; std_deviation_sampling_as_string: string; std_deviation_bounds_as_string: { upper: string; lower: string; upper_population: string; lower_population: string; upper_sampling: string; lower_sampling: string; }; }); extended_stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number | null; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; }; filter: { doc_count: number; } & SubAggregateOf; filters: { buckets: TAggregationContainer extends { filters: { filters: any[]; }; } ? ({ doc_count: number; } & SubAggregateOf)[] : TAggregationContainer extends { filters: { filters: Record; }; } ? { [key in keyof TAggregationContainer[\"filters\"][\"filters\"]]: { doc_count: number; } & SubAggregateOf; } & (TAggregationContainer extends { filters: { other_bucket_key: infer TOtherBucketKey; }; } ? Record> : unknown) & (TAggregationContainer extends { filters: { other_bucket: true; }; } ? { _other: { doc_count: number; } & SubAggregateOf; } : unknown) : unknown; }; geo_bounds: { top_left: { lat: number | null; lon: number | null; }; bottom_right: { lat: number | null; lon: number | null; }; }; geo_centroid: { count: number; location: { lat: number; lon: number; }; }; geo_distance: MaybeKeyed, string>; geo_hash: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; geotile_grid: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; global: { doc_count: number; } & SubAggregateOf; histogram: MaybeKeyed, string>; ip_range: MaybeKeyed; inference: { value: number; prediction_probability: number; prediction_score: number; }; max: { value: number | null; value_as_string?: string | undefined; }; max_bucket: { value: number | null; }; min: { value: number | null; value_as_string?: string | undefined; }; min_bucket: { value: number | null; }; median_absolute_deviation: { value: number | null; }; moving_avg: { value: number | null; } | undefined; moving_fn: { value: number | null; }; moving_percentiles: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record | undefined; missing: { doc_count: number; } & SubAggregateOf; multi_terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string[]; } & SubAggregateOf)[]; }; nested: { doc_count: number; } & SubAggregateOf; normalize: { value: number | null; value_as_string?: string | undefined; }; parent: { doc_count: number; } & SubAggregateOf; percentiles: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentile_ranks: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentiles_bucket: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; range: MaybeKeyed; rare_terms: ({ key: string | number; doc_count: number; } & SubAggregateOf)[]; rate: { value: number | null; }; reverse_nested: { doc_count: number; } & SubAggregateOf; random_sampler: { seed: number; probability: number; doc_count: number; } & SubAggregateOf; sampler: { doc_count: number; } & SubAggregateOf; scripted_metric: { value: unknown; }; serial_diff: { value: number | null; value_as_string?: string | undefined; }; significant_terms: { doc_count: number; bg_count: number; buckets: ({ key: string | number; score: number; doc_count: number; bg_count: number; } & SubAggregateOf)[]; }; significant_text: { doc_count: number; buckets: { key: string; doc_count: number; score: number; bg_count: number; }[]; }; stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_as_string: string; }); stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; }; string_stats: { count: number; min_length: number | null; max_length: number | null; avg_length: number | null; entropy: number | null; distribution: Record; }; sum: { value: number | null; value_as_string?: string | undefined; }; sum_bucket: { value: number | null; }; terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string | number; key_as_string?: string | undefined; } & SubAggregateOf)[]; }; top_hits: { hits: { total: { value: number; relation: \"gte\" | \"eq\"; }; max_score: number | null; hits: TAggregationContainer extends { top_hits: ", + "AggregationsTopHitsAggregation", + "; } ? HitsOf : ", + "SearchHitsMetadata", + "; }; }; top_metrics: { top: { sort: string[] | number[]; metrics: Record, string | number | null>; }[]; }; weighted_avg: { value: number | null; }; value_count: { value: number; }; }, Exclude, \"aggs\" | \"aggregations\"> & string> extends object ? Pick & { adjacency_matrix: { buckets: ({ key: string; doc_count: number; } & SubAggregateOf)[]; }; auto_date_histogram: { interval: string; buckets: ({ key: number; key_as_string: string; doc_count: number; } & SubAggregateOf)[]; }; avg: { value: number | null; value_as_string?: string | undefined; }; avg_bucket: { value: number | null; }; boxplot: { min: number | null; max: number | null; q1: number | null; q2: number | null; q3: number | null; }; bucket_correlation: { value: number | null; }; bucket_count_ks_test: { less: number; greater: number; two_sided: number; }; bucket_script: { value: unknown; }; cardinality: { value: number; }; children: { doc_count: number; } & SubAggregateOf; composite: { after_key: CompositeKeysOf; buckets: ({ doc_count: number; key: CompositeKeysOf; } & SubAggregateOf)[]; }; cumulative_cardinality: { value: number; }; cumulative_sum: { value: number; }; date_histogram: MaybeKeyed, string>; date_range: MaybeKeyed & Partial<{ to: string | number; to_as_string: string; }> & { doc_count: number; key: string; }, string>; derivative: { value: number | null; } | undefined; extended_stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_of_squares_as_string: string; variance_population_as_string: string; variance_sampling_as_string: string; std_deviation_as_string: string; std_deviation_population_as_string: string; std_deviation_sampling_as_string: string; std_deviation_bounds_as_string: { upper: string; lower: string; upper_population: string; lower_population: string; upper_sampling: string; lower_sampling: string; }; }); extended_stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number | null; sum_of_squares: number | null; variance: number | null; variance_population: number | null; variance_sampling: number | null; std_deviation: number | null; std_deviation_population: number | null; std_deviation_sampling: number | null; std_deviation_bounds: { upper: number | null; lower: number | null; upper_population: number | null; lower_population: number | null; upper_sampling: number | null; lower_sampling: number | null; }; }; filter: { doc_count: number; } & SubAggregateOf; filters: { buckets: TAggregationContainer extends { filters: { filters: any[]; }; } ? ({ doc_count: number; } & SubAggregateOf)[] : TAggregationContainer extends { filters: { filters: Record; }; } ? { [key in keyof TAggregationContainer[\"filters\"][\"filters\"]]: { doc_count: number; } & SubAggregateOf; } & (TAggregationContainer extends { filters: { other_bucket_key: infer TOtherBucketKey; }; } ? Record> : unknown) & (TAggregationContainer extends { filters: { other_bucket: true; }; } ? { _other: { doc_count: number; } & SubAggregateOf; } : unknown) : unknown; }; geo_bounds: { top_left: { lat: number | null; lon: number | null; }; bottom_right: { lat: number | null; lon: number | null; }; }; geo_centroid: { count: number; location: { lat: number; lon: number; }; }; geo_distance: MaybeKeyed, string>; geo_hash: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; geotile_grid: { buckets: ({ doc_count: number; key: string; } & SubAggregateOf)[]; }; global: { doc_count: number; } & SubAggregateOf; histogram: MaybeKeyed, string>; ip_range: MaybeKeyed; inference: { value: number; prediction_probability: number; prediction_score: number; }; max: { value: number | null; value_as_string?: string | undefined; }; max_bucket: { value: number | null; }; min: { value: number | null; value_as_string?: string | undefined; }; min_bucket: { value: number | null; }; median_absolute_deviation: { value: number | null; }; moving_avg: { value: number | null; } | undefined; moving_fn: { value: number | null; }; moving_percentiles: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record | undefined; missing: { doc_count: number; } & SubAggregateOf; multi_terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string[]; } & SubAggregateOf)[]; }; nested: { doc_count: number; } & SubAggregateOf; normalize: { value: number | null; value_as_string?: string | undefined; }; parent: { doc_count: number; } & SubAggregateOf; percentiles: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentile_ranks: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; percentiles_bucket: { values: TAggregationContainer extends Record ? { key: number; value: number | null; }[] : Record; }; range: MaybeKeyed; rare_terms: ({ key: string | number; doc_count: number; } & SubAggregateOf)[]; rate: { value: number | null; }; reverse_nested: { doc_count: number; } & SubAggregateOf; random_sampler: { seed: number; probability: number; doc_count: number; } & SubAggregateOf; sampler: { doc_count: number; } & SubAggregateOf; scripted_metric: { value: unknown; }; serial_diff: { value: number | null; value_as_string?: string | undefined; }; significant_terms: { doc_count: number; bg_count: number; buckets: ({ key: string | number; score: number; doc_count: number; bg_count: number; } & SubAggregateOf)[]; }; significant_text: { doc_count: number; buckets: { key: string; doc_count: number; score: number; bg_count: number; }[]; }; stats: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; } & ({} | { min_as_string: string; max_as_string: string; avg_as_string: string; sum_as_string: string; }); stats_bucket: { count: number; min: number | null; max: number | null; avg: number | null; sum: number; }; string_stats: { count: number; min_length: number | null; max_length: number | null; avg_length: number | null; entropy: number | null; distribution: Record; }; sum: { value: number | null; value_as_string?: string | undefined; }; sum_bucket: { value: number | null; }; terms: { doc_count_error_upper_bound: number; sum_other_doc_count: number; buckets: ({ doc_count: number; key: string | number; key_as_string?: string | undefined; } & SubAggregateOf)[]; }; top_hits: { hits: { total: { value: number; relation: \"gte\" | \"eq\"; }; max_score: number | null; hits: TAggregationContainer extends { top_hits: ", + "AggregationsTopHitsAggregation", + "; } ? HitsOf : ", + "SearchHitsMetadata", + "; }; }; top_metrics: { top: { sort: string[] | number[]; metrics: Record, string | number | null>; }[]; }; weighted_avg: { value: number | null; }; value_count: { value: number; }; }, Exclude, \"aggs\" | \"aggregations\"> & string>[Exclude, \"aggs\" | \"aggregations\"> & string] : never" + ], + "path": "packages/kbn-es-types/src/search.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.AggregationOptionsByType", + "type": "Type", + "tags": [], + "label": "AggregationOptionsByType", + "description": [], + "signature": [ + "{ aggregations: Record; aggs: Record; meta: ", + "Metadata", + "; adjacency_matrix: ", + "AggregationsAdjacencyMatrixAggregation", + "; auto_date_histogram: ", + "AggregationsAutoDateHistogramAggregation", + "; avg: ", + "AggregationsAverageAggregation", + "; avg_bucket: ", + "AggregationsAverageBucketAggregation", + "; boxplot: ", + "AggregationsBoxplotAggregation", + "; bucket_script: ", + "AggregationsBucketScriptAggregation", + "; bucket_selector: ", + "AggregationsBucketSelectorAggregation", + "; bucket_sort: ", + "AggregationsBucketSortAggregation", + "; bucket_count_ks_test: ", + "AggregationsBucketKsAggregation", + "; bucket_correlation: ", + "AggregationsBucketCorrelationAggregation", + "; cardinality: ", + "AggregationsCardinalityAggregation", + "; categorize_text: ", + "AggregationsCategorizeTextAggregation", + "; children: ", + "AggregationsChildrenAggregation", + "; composite: ", + "AggregationsCompositeAggregation", + "; cumulative_cardinality: ", + "AggregationsCumulativeCardinalityAggregation", + "; cumulative_sum: ", + "AggregationsCumulativeSumAggregation", + "; date_histogram: ", + "AggregationsDateHistogramAggregation", + "; date_range: ", + "AggregationsDateRangeAggregation", + "; derivative: ", + "AggregationsDerivativeAggregation", + "; diversified_sampler: ", + "AggregationsDiversifiedSamplerAggregation", + "; extended_stats: ", + "AggregationsExtendedStatsAggregation", + "; extended_stats_bucket: ", + "AggregationsExtendedStatsBucketAggregation", + "; filter: ", + "QueryDslQueryContainer", + "; filters: ", + "AggregationsFiltersAggregation", + "; geo_bounds: ", + "AggregationsGeoBoundsAggregation", + "; geo_centroid: ", + "AggregationsGeoCentroidAggregation", + "; geo_distance: ", + "AggregationsGeoDistanceAggregation", + "; geohash_grid: ", + "AggregationsGeoHashGridAggregation", + "; geo_line: ", + "AggregationsGeoLineAggregation", + "; geotile_grid: ", + "AggregationsGeoTileGridAggregation", + "; geohex_grid: ", + "AggregationsGeohexGridAggregation", + "; global: ", + "AggregationsGlobalAggregation", + "; histogram: ", + "AggregationsHistogramAggregation", + "; ip_range: ", + "AggregationsIpRangeAggregation", + "; inference: ", + "AggregationsInferenceAggregation", + "; line: ", + "AggregationsGeoLineAggregation", + "; matrix_stats: ", + "AggregationsMatrixStatsAggregation", + "; max: ", + "AggregationsMaxAggregation", + "; max_bucket: ", + "AggregationsMaxBucketAggregation", + "; median_absolute_deviation: ", + "AggregationsMedianAbsoluteDeviationAggregation", + "; min: ", + "AggregationsMinAggregation", + "; min_bucket: ", + "AggregationsMinBucketAggregation", + "; missing: ", + "AggregationsMissingAggregation", + "; moving_avg: ", + "AggregationsMovingAverageAggregation", + "; moving_percentiles: ", + "AggregationsMovingPercentilesAggregation", + "; moving_fn: ", + "AggregationsMovingFunctionAggregation", + "; multi_terms: ", + "AggregationsMultiTermsAggregation", + "; nested: ", + "AggregationsNestedAggregation", + "; normalize: ", + "AggregationsNormalizeAggregation", + "; parent: ", + "AggregationsParentAggregation", + "; percentile_ranks: ", + "AggregationsPercentileRanksAggregation", + "; percentiles: ", + "AggregationsPercentilesAggregation", + "; percentiles_bucket: ", + "AggregationsPercentilesBucketAggregation", + "; range: ", + "AggregationsRangeAggregation", + "; rare_terms: ", + "AggregationsRareTermsAggregation", + "; rate: ", + "AggregationsRateAggregation", + "; reverse_nested: ", + "AggregationsReverseNestedAggregation", + "; sampler: ", + "AggregationsSamplerAggregation", + "; scripted_metric: ", + "AggregationsScriptedMetricAggregation", + "; serial_diff: ", + "AggregationsSerialDifferencingAggregation", + "; significant_terms: ", + "AggregationsSignificantTermsAggregation", + "; significant_text: ", + "AggregationsSignificantTextAggregation", + "; stats: ", + "AggregationsStatsAggregation", + "; stats_bucket: ", + "AggregationsStatsBucketAggregation", + "; string_stats: ", + "AggregationsStringStatsAggregation", + "; sum: ", + "AggregationsSumAggregation", + "; sum_bucket: ", + "AggregationsSumBucketAggregation", + "; terms: ", + "AggregationsTermsAggregation", + "; top_hits: ", + "AggregationsTopHitsAggregation", + "; t_test: ", + "AggregationsTTestAggregation", + "; top_metrics: ", + "AggregationsTopMetricsAggregation", + "; value_count: ", + "AggregationsValueCountAggregation", + "; weighted_avg: ", + "AggregationsWeightedAverageAggregation", + "; variable_width_histogram: ", + "AggregationsVariableWidthHistogramAggregation", + "; }" + ], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.ESFilter", + "type": "Type", + "tags": [], + "label": "ESFilter", + "description": [], + "signature": [ + "QueryDslQueryContainer" + ], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.ESSearchRequest", + "type": "Type", + "tags": [], + "label": "ESSearchRequest", + "description": [], + "signature": [ + "SearchRequest" + ], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.ESSearchResponse", + "type": "Type", + "tags": [], + "label": "ESSearchResponse", + "description": [], + "signature": [ + "Omit<", + "SearchResponse", + ">, \"hits\" | \"aggregations\"> & (TSearchRequest[\"body\"] extends TopLevelAggregationRequest ? WrapAggregationResponse> : TSearchRequest extends TopLevelAggregationRequest ? WrapAggregationResponse> : { aggregations?: unknown; }) & { hits: Omit<", + "SearchHitsMetadata", + ", \"hits\" | \"total\"> & (TOptions[\"restTotalHitsAsInt\"] extends true ? { total: number; } : { total: { value: number; relation: \"gte\" | \"eq\"; }; }) & { hits: HitsOf | undefined; aggs?: Record | undefined; collapse?: ", + "SearchFieldCollapse", + " | undefined; explain?: boolean | undefined; from?: number | undefined; highlight?: ", + "SearchHighlight", + " | undefined; track_total_hits?: ", + "SearchTrackHits", + " | undefined; indices_boost?: Record[] | undefined; docvalue_fields?: (string | ", + "QueryDslFieldAndFormat", + ")[] | undefined; min_score?: number | undefined; post_filter?: ", + "QueryDslQueryContainer", + " | undefined; profile?: boolean | undefined; query?: ", + "QueryDslQueryContainer", + " | undefined; rescore?: ", + "SearchRescore", + " | ", + "SearchRescore", + "[] | undefined; script_fields?: Record | undefined; search_after?: ", + "SortResults", + " | undefined; size?: number | undefined; slice?: ", + "SlicedScroll", + " | undefined; sort?: ", + "Sort", + " | undefined; _source?: ", + "SearchSourceConfig", + " | undefined; fields?: (string | ", + "QueryDslFieldAndFormat", + ")[] | undefined; suggest?: ", + "SearchSuggester", + " | undefined; terminate_after?: number | undefined; timeout?: string | undefined; track_scores?: boolean | undefined; version?: boolean | undefined; seq_no_primary_term?: boolean | undefined; stored_fields?: ", + "Fields", + " | undefined; pit?: ", + "SearchPointInTimeReference", + " | undefined; runtime_mappings?: ", + "MappingRuntimeFields", + " | undefined; stats?: string[] | undefined; } | undefined ? TSearchRequest[\"body\"] : TSearchRequest, TDocument>; }; }" + ], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.ESSourceOptions", + "type": "Type", + "tags": [], + "label": "ESSourceOptions", + "description": [], + "signature": [ + "string | boolean | string[]" + ], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.InferSearchResponseOf", + "type": "Type", + "tags": [], + "label": "InferSearchResponseOf", + "description": [], + "signature": [ + "Omit<", + "SearchResponse", + ">, \"hits\" | \"aggregations\"> & (TSearchRequest[\"body\"] extends TopLevelAggregationRequest ? WrapAggregationResponse> : TSearchRequest extends TopLevelAggregationRequest ? WrapAggregationResponse> : { aggregations?: unknown; }) & { hits: Omit<", + "SearchHitsMetadata", + ", \"hits\" | \"total\"> & (TOptions[\"restTotalHitsAsInt\"] extends true ? { total: number; } : { total: { value: number; relation: \"gte\" | \"eq\"; }; }) & { hits: HitsOf | undefined; aggs?: Record | undefined; collapse?: ", + "SearchFieldCollapse", + " | undefined; explain?: boolean | undefined; from?: number | undefined; highlight?: ", + "SearchHighlight", + " | undefined; track_total_hits?: ", + "SearchTrackHits", + " | undefined; indices_boost?: Record[] | undefined; docvalue_fields?: (string | ", + "QueryDslFieldAndFormat", + ")[] | undefined; min_score?: number | undefined; post_filter?: ", + "QueryDslQueryContainer", + " | undefined; profile?: boolean | undefined; query?: ", + "QueryDslQueryContainer", + " | undefined; rescore?: ", + "SearchRescore", + " | ", + "SearchRescore", + "[] | undefined; script_fields?: Record | undefined; search_after?: ", + "SortResults", + " | undefined; size?: number | undefined; slice?: ", + "SlicedScroll", + " | undefined; sort?: ", + "Sort", + " | undefined; _source?: ", + "SearchSourceConfig", + " | undefined; fields?: (string | ", + "QueryDslFieldAndFormat", + ")[] | undefined; suggest?: ", + "SearchSuggester", + " | undefined; terminate_after?: number | undefined; timeout?: string | undefined; track_scores?: boolean | undefined; version?: boolean | undefined; seq_no_primary_term?: boolean | undefined; stored_fields?: ", + "Fields", + " | undefined; pit?: ", + "SearchPointInTimeReference", + " | undefined; runtime_mappings?: ", + "MappingRuntimeFields", + " | undefined; stats?: string[] | undefined; } | undefined ? TSearchRequest[\"body\"] : TSearchRequest, TDocument>; }; }" + ], + "path": "packages/kbn-es-types/src/search.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.MaybeReadonlyArray", + "type": "Type", + "tags": [], + "label": "MaybeReadonlyArray", + "description": [], + "signature": [ + "T[] | readonly T[]" + ], + "path": "packages/kbn-es-types/src/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/es-types", + "id": "def-server.SearchHit", + "type": "Type", + "tags": [], + "label": "SearchHit", + "description": [], + "signature": [ + "Omit<", + "SearchHit", + ", \"fields\" | \"_source\"> & (TSource extends false ? {} : { _source: TSource; }) & (TFields extends (string | ", + "QueryDslFieldAndFormat", + ")[] ? { fields: Partial, unknown[]>>; } : {}) & (TDocValueFields extends DocValueFields ? { fields: Partial, unknown[]>>; } : {})" + ], + "path": "packages/kbn-es-types/src/search.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx new file mode 100644 index 0000000000000..95466ada26028 --- /dev/null +++ b/api_docs/kbn_es_types.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: kibKbnEsTypesPluginApi +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: 2022-09-21 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] +--- +import kbnEsTypesObj from './kbn_es_types.devdocs.json'; + + + +Contact Kibana Core for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 11 | 0 | 11 | 0 | + +## Server + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index c555fe8b7d5a5..7f2a5f8ffbca4 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 0e498ea0e9b54..94177dc5aa243 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index eaeb3333485b0..44625438cd032 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: 2022-09-20 +date: 2022-09-21 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_generate.mdx b/api_docs/kbn_generate.mdx index 3bcaf385b30d3..af968a0d6c12b 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 32da58c287d17..eb3041437f858 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index b619dcc8fce29..ea945e927f03b 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: 2022-09-20 +date: 2022-09-21 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 6010e62895745..5d79694335b6b 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 63fa535614bb5..94506cf8d9909 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: 2022-09-20 +date: 2022-09-21 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 73678fded69f2..0d4b974929b83 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: 2022-09-20 +date: 2022-09-21 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 6a2be69a99536..bf4c70817d7bc 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 55418c0839d6d..d051acb699996 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index dcd0bbfddac67..7d0955caeb361 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 2b192f2ae841e..b6c9a79910594 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index dfe4988fde861..4ed4996625614 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 61d0fe628c129..e1edaaac04cc2 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 7c2d9e7844a11..b8e4bbc6d85d7 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: 2022-09-20 +date: 2022-09-21 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 355064817f4d6..cdf7e9493bfde 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 99845433826f3..3f07937de52fe 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 6780c1f696b69..bc63c5e56f04c 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.devdocs.json b/api_docs/kbn_ml_agg_utils.devdocs.json index ced4750717a78..6c021a7a5bc78 100644 --- a/api_docs/kbn_ml_agg_utils.devdocs.json +++ b/api_docs/kbn_ml_agg_utils.devdocs.json @@ -637,6 +637,17 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "@kbn/ml-agg-utils", + "id": "def-server.ChangePointGroup.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/packages/ml/agg_utils/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/ml-agg-utils", "id": "def-server.ChangePointGroup.group", @@ -661,6 +672,89 @@ "path": "x-pack/packages/ml/agg_utils/src/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ml-agg-utils", + "id": "def-server.ChangePointGroup.pValue", + "type": "CompoundType", + "tags": [], + "label": "pValue", + "description": [], + "signature": [ + "number | null" + ], + "path": "x-pack/packages/ml/agg_utils/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ml-agg-utils", + "id": "def-server.ChangePointGroup.histogram", + "type": "Array", + "tags": [], + "label": "histogram", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ml-agg-utils", + "scope": "server", + "docId": "kibKbnMlAggUtilsPluginApi", + "section": "def-server.ChangePointHistogramItem", + "text": "ChangePointHistogramItem" + }, + "[] | undefined" + ], + "path": "x-pack/packages/ml/agg_utils/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ml-agg-utils", + "id": "def-server.ChangePointGroupHistogram", + "type": "Interface", + "tags": [], + "label": "ChangePointGroupHistogram", + "description": [ + "\nChange point histogram data for a group of field/value pairs." + ], + "path": "x-pack/packages/ml/agg_utils/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ml-agg-utils", + "id": "def-server.ChangePointGroupHistogram.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/packages/ml/agg_utils/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ml-agg-utils", + "id": "def-server.ChangePointGroupHistogram.histogram", + "type": "Array", + "tags": [], + "label": "histogram", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ml-agg-utils", + "scope": "server", + "docId": "kibKbnMlAggUtilsPluginApi", + "section": "def-server.ChangePointHistogramItem", + "text": "ChangePointHistogramItem" + }, + "[]" + ], + "path": "x-pack/packages/ml/agg_utils/src/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index adadb5a8d1141..20d206ee85420 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact Machine Learning UI for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 58 | 2 | 39 | 3 | +| 64 | 2 | 44 | 3 | ## Server diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 1bd52ce9c5bc8..f03e2c0dd1368 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: 2022-09-20 +date: 2022-09-21 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_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 372c7969c3806..f5c6ec4dab20c 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 902578461f024..4a2b7d251d645 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index cbc5ae1b1ded5..9dec2e2d12388 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: 2022-09-20 +date: 2022-09-21 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 42c37c78b5178..3ecb10b8ce84a 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 44d6ca0550963..629055ccc04e7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 4798bfbf8987a..f2e631ec8cd4b 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: 2022-09-20 +date: 2022-09-21 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 b9be224e32a5b..b7141c78f3cf9 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 40fa48fd2b023..5a9f1942a5bd6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 1509876385b1f..0e6aab2d83377 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 0e8c7c73e7c84..c4061ab88aac1 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 6e19f121fd9ad..fd9731c4d32f5 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 2ffb661273b81..ec574df2ac420 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: 2022-09-20 +date: 2022-09-21 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_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 7e05e5af14825..060150aec0633 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: 2022-09-20 +date: 2022-09-21 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 d94c62d645fd5..1c47b09302c0e 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: 2022-09-20 +date: 2022-09-21 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 63986072c7322..343773fc6961f 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: 2022-09-20 +date: 2022-09-21 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 7a0b917859a62..5b6f8c7121eb2 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: 2022-09-20 +date: 2022-09-21 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 6177ab6c92c8d..d91fd25457476 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: 2022-09-20 +date: 2022-09-21 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 4b880041473c4..47970932a1793 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: 2022-09-20 +date: 2022-09-21 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 28cf4efef38a8..34e695f21aeea 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: 2022-09-20 +date: 2022-09-21 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 e2232050612c1..e58504680e2cf 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: 2022-09-20 +date: 2022-09-21 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 44b7742d2b5c7..a87cfd6fe0973 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: 2022-09-20 +date: 2022-09-21 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 b979309b06fc5..ff535c6f560d9 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: 2022-09-20 +date: 2022-09-21 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 fd74c70883973..5df5c3218e6a1 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: 2022-09-20 +date: 2022-09-21 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 0acf0fc188b95..fc58053025b36 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: 2022-09-20 +date: 2022-09-21 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 be7aff880057c..1af486fce1c5e 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: 2022-09-20 +date: 2022-09-21 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 bdba63997b786..b743139813871 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 5cf5c679becea..78782a2742f93 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: 2022-09-20 +date: 2022-09-21 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_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 8032ad63fef85..9d1ce452077a0 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 50578bc364b66..86f562d4bb410 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 453fd4a07cd2c..534731ed2ed6c 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.devdocs.json b/api_docs/kbn_shared_ux_card_no_data.devdocs.json index a97e211368c5c..c1e08d1b9a31f 100644 --- a/api_docs/kbn_shared_ux_card_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data.devdocs.json @@ -186,7 +186,11 @@ "signature": [ "{ children?: React.ReactNode; description?: React.ReactNode; category?: string | undefined; onError?: React.ReactEventHandler | undefined; hidden?: boolean | undefined; icon?: React.ReactElement<", "EuiIconProps", - ", string | React.JSXElementConstructor> | null | undefined; id?: string | undefined; image?: string | React.ReactElement> | undefined; className?: string | undefined; title?: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | undefined; onChange?: React.FormEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; href?: string | undefined; rel?: string | undefined; target?: string | undefined; paddingSize?: \"none\" | \"m\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined; button?: React.ReactNode; footer?: React.ReactNode; hasBorder?: boolean | undefined; textAlign?: CardAlignment | undefined; titleElement?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"span\" | undefined; titleSize?: \"s\" | \"xs\" | undefined; betaBadgeProps?: Partial<(", + ", string | React.JSXElementConstructor> | null | undefined; id?: string | undefined; image?: string | React.ReactElement> | undefined; className?: string | undefined; title?: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | undefined; onChange?: React.FormEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", + "Interpolation", + "<", + "Theme", + ">; href?: string | undefined; rel?: string | undefined; target?: string | undefined; paddingSize?: \"none\" | \"m\" | \"s\" | \"xs\" | \"l\" | \"xl\" | undefined; button?: React.ReactNode; footer?: React.ReactNode; hasBorder?: boolean | undefined; textAlign?: CardAlignment | undefined; titleElement?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"span\" | undefined; titleSize?: \"s\" | \"xs\" | undefined; betaBadgeProps?: Partial<(", "CommonProps", " & ", "DisambiguateSet", diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 8f8e2cb2d0840..3b9307fe75198 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: 2022-09-20 +date: 2022-09-21 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 6b5cf577d2f23..d8a57acd59459 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: 2022-09-20 +date: 2022-09-21 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_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index ad46fe9c6337f..29650e5ed8646 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: 2022-09-20 +date: 2022-09-21 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_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 650f6b6de6657..9962da3b57786 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: 2022-09-20 +date: 2022-09-21 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 c526e3b3d7f6d..f5e9eec99917c 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: 2022-09-20 +date: 2022-09-21 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 620084197a3fc..2123307bc9e97 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: 2022-09-20 +date: 2022-09-21 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 53fe5c2b52348..e09c5179542e1 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 1cc01f097e1f5..17b290a187bd0 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: 2022-09-20 +date: 2022-09-21 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 294ae75484592..0624865a7cb3e 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: 2022-09-20 +date: 2022-09-21 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 e228084b30143..5a3f2d93ec15d 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 02191cc87e73d..158d91473e56c 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: 2022-09-20 +date: 2022-09-21 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 aa10464a8a61e..8f4d8b0219143 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: 2022-09-20 +date: 2022-09-21 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 0ac409eb1f626..fe62493020308 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 113d794aeac30..c95da8b4cc92f 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 784d4bbb54fd0..655e11aa964bf 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: 2022-09-20 +date: 2022-09-21 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 5097f00e1394f..db40292785ab2 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: 2022-09-20 +date: 2022-09-21 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_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 576f834d1cf4e..5824ea5c73c58 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: 2022-09-20 +date: 2022-09-21 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 75a3bdd71f467..8ec6570a0220e 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: 2022-09-20 +date: 2022-09-21 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 9fc0023c3105f..d9814c190f09f 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: 2022-09-20 +date: 2022-09-21 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 6e659b6749e9b..6744b6d0e1dcd 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index ae651ff396bb2..c3d29d99df19d 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index a5bf07dccef17..80d98d2a35ebe 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: 2022-09-20 +date: 2022-09-21 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_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index bec95f5dd0edf..e149b42881f92 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 15d38db3ce3f8..349e5920113d0 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: 2022-09-20 +date: 2022-09-21 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 286713890035f..99f2f0c8664b2 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: 2022-09-20 +date: 2022-09-21 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 6dcb31e2935ba..8c97882f6aa61 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index f55b78a57dd13..83166d900d2ed 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: 2022-09-20 +date: 2022-09-21 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 368a220dbf198..9230fac245d35 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index a9bab53131ebc..1e3817ccdee9f 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: 2022-09-20 +date: 2022-09-21 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 32bfe1cb2f68b..53a5a76b85ff3 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 4e928b81cc9e2..054c0285c637d 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index 6885c76d34578..afa19269f8816 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index 02d17639ecacb..8c4e404667da3 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index eee639c93e87c..805990c966ba5 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: 2022-09-20 +date: 2022-09-21 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_theme.devdocs.json b/api_docs/kbn_ui_theme.devdocs.json index c378173a45f13..6dcb3db66223b 100644 --- a/api_docs/kbn_ui_theme.devdocs.json +++ b/api_docs/kbn_ui_theme.devdocs.json @@ -54,7 +54,7 @@ "label": "Theme", "description": [], "signature": [ - "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiPopoverArrowSize: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" + "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" ], "path": "packages/kbn-ui-theme/src/theme.ts", "deprecated": false, @@ -86,7 +86,7 @@ "label": "euiDarkVars", "description": [], "signature": [ - "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiPopoverArrowSize: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" + "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" ], "path": "packages/kbn-ui-theme/src/theme.ts", "deprecated": false, @@ -101,7 +101,7 @@ "label": "euiLightVars", "description": [], "signature": [ - "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiPopoverArrowSize: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" + "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" ], "path": "packages/kbn-ui-theme/src/theme.ts", "deprecated": false, @@ -118,7 +118,7 @@ "\nEUI Theme vars that automatically adjust to light/dark theme" ], "signature": [ - "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiPopoverArrowSize: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" + "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" ], "path": "packages/kbn-ui-theme/src/theme.ts", "deprecated": false, diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 76f96eb38b6e5..64654b10b3002 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 93b401d3f3979..e4d20bc32a22e 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: 2022-09-20 +date: 2022-09-21 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 70061bff2f395..a2ab571bf69fa 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: 2022-09-20 +date: 2022-09-21 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 0161668a526f1..0767b1a144f7e 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: 2022-09-20 +date: 2022-09-21 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 58b9be7f437c9..c937c340e4433 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 79ee7cd9f2a58..64f290c135730 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 3fe57352b3d88..da1c2cc403976 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.devdocs.json b/api_docs/kibana_react.devdocs.json index 5677d3738d59b..67182ef5aede3 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -672,7 +672,7 @@ "label": "KibanaThemeProvider", "description": [], "signature": [ - "({ theme$, children }: React.PropsWithChildren) => JSX.Element" + "({ theme$, modify, children }: React.PropsWithChildren) => JSX.Element" ], "path": "src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx", "deprecated": false, @@ -683,7 +683,7 @@ "id": "def-public.KibanaThemeProvider.$1", "type": "CompoundType", "tags": [], - "label": "{ theme$, children }", + "label": "{ theme$, modify, children }", "description": [], "signature": [ "React.PropsWithChildren" @@ -3893,7 +3893,7 @@ "label": "eui", "description": [], "signature": [ - "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiPopoverArrowSize: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" + "{ euiBadgeGroupGutterTypes: { gutterExtraSmall: string; gutterSmall: string; }; euiButtonEmptyTypes: { primary: string; danger: string; disabled: string; ghost: string; text: string; success: string; warning: string; }; euiCallOutTypes: { primary: string; success: string; warning: string; danger: string; }; euiCardSpacing: string; euiCardBottomNodeHeight: string; euiCardSelectButtonBorders: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardSelectButtonBackgrounds: { text: string; primary: string; success: string; danger: string; ghost: string; }; euiCardPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCheckableCardPadding: string; euiCodeBlockPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiCollapsibleNavGroupLightBackgroundColor: string; euiCollapsibleNavGroupDarkBackgroundColor: string; euiCollapsibleNavGroupDarkHighContrastColor: string; euiColorPickerValueRange0: string; euiColorPickerValueRange1: string; euiColorPickerSaturationRange0: string; euiColorPickerSaturationRange1: string; euiColorPickerIndicatorSize: string; euiColorPickerWidth: string; euiColorPaletteDisplaySizes: { sizeExtraSmall: string; sizeSmall: string; sizeMedium: string; }; euiContextMenuWidth: string; euiControlBarBackground: string; euiControlBarText: string; euiControlBarBorderColor: string; euiControlBarInitialHeight: string; euiControlBarMaxHeight: string; euiControlBarHeights: { s: string; m: string; l: string; }; euiDataGridPrefix: string; euiDataGridStyles: string; euiZDataGrid: number; euiZHeaderBelowDataGrid: number; euiZDataGridCellPopover: number; euiDataGridColumnResizerWidth: string; euiDataGridPopoverMaxHeight: string; euiDataGridCellPaddingS: string; euiDataGridCellPaddingM: string; euiDataGridCellPaddingL: string; euiDataGridVerticalBorder: string; euiSuperDatePickerWidth: string; euiSuperDatePickerButtonWidth: string; euiDragAndDropSpacing: { s: string; m: string; l: string; }; euiEmptyPromptContentMaxWidth: string; gutterTypes: { gutterExtraSmall: string; gutterSmall: string; gutterMedium: string; gutterLarge: string; gutterExtraLarge: string; }; fractions: { fourths: { percentage: string; count: number; }; thirds: { percentage: string; count: number; }; halves: { percentage: string; count: number; }; single: { percentage: string; count: number; }; }; flyoutSizes: { small: { min: string; width: string; max: string; }; medium: { min: string; width: string; max: string; }; large: { min: string; width: string; max: string; }; }; euiFlyoutBorder: string; euiFlyoutPaddingModifiers: { paddingNone: number; paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiFilePickerTallHeight: string; euiRangeLevelColors: { primary: string; success: string; warning: string; danger: string; }; textareaResizing: { vertical: string; horizontal: string; both: string; none: string; }; euiHeaderLinksGutterSizes: { gutterXS: string; gutterS: string; gutterM: string; gutterL: string; }; euiKeyPadMenuSize: string; euiKeyPadMenuMarginSize: string; euiListGroupItemHoverBackground: string; euiListGroupItemHoverBackgroundGhost: string; euiListGroupGutterTypes: { gutterSmall: string; gutterMedium: string; }; euiListGroupItemColorTypes: { primary: string; text: string; subdued: string; ghost: string; }; euiListGroupItemSizeTypes: { xSmall: string; small: string; medium: string; large: string; }; euiMarkdownEditorMinHeight: string; euiResizableButtonTransitionSpeed: string; euiResizableButtonSize: string; euiSelectableListItemBorder: string; euiSelectableListItemPadding: string; euiSelectableTemplateSitewideTypes: { application: { color: string; 'font-weight': number; }; deployment: { color: string; 'font-weight': number; }; article: { color: string; 'font-weight': number; }; case: { color: string; 'font-weight': number; }; platform: { color: string; 'font-weight': number; }; }; euiSideNavEmphasizedBackgroundColor: string; euiSideNavRootTextcolor: string; euiSideNavBranchTextcolor: string; euiSideNavSelectedTextcolor: string; euiSideNavDisabledTextcolor: string; euiStepNumberSize: string; euiStepNumberSmallSize: string; euiStepNumberMargin: string; euiStepStatusColorsToFade: { warning: string; danger: string; disabled: string; incomplete: string; }; euiSuggestItemColors: { tint0: string; tint1: string; tint2: string; tint3: string; tint4: string; tint5: string; tint6: string; tint7: string; tint8: string; tint9: string; tint10: string; }; euiTableCellContentPadding: string; euiTableCellContentPaddingCompressed: string; euiTableCellCheckboxWidth: string; euiTableActionsAreaWidth: string; euiTableHoverColor: string; euiTableSelectedColor: string; euiTableHoverSelectedColor: string; euiTableActionsBorderColor: string; euiTableHoverClickableColor: string; euiTableFocusClickableColor: string; euiContrastRatioText: number; euiContrastRatioGraphic: number; euiContrastRatioDisabled: number; euiAnimSlightBounce: string; euiAnimSlightResistance: string; euiAnimSpeedExtraFast: string; euiAnimSpeedFast: string; euiAnimSpeedNormal: string; euiAnimSpeedSlow: string; euiAnimSpeedExtraSlow: string; euiBorderWidthThin: string; euiBorderWidthThick: string; euiBorderColor: string; euiBorderRadius: string; euiBorderRadiusSmall: string; euiBorderThick: string; euiBorderThin: string; euiBorderEditable: string; euiButtonHeight: string; euiButtonHeightSmall: string; euiButtonHeightXSmall: string; euiButtonColorDisabled: string; euiButtonColorDisabledText: string; euiButtonColorGhostDisabled: string; euiButtonTypes: { primary: string; accent: string; success: string; warning: string; danger: string; ghost: string; text: string; }; euiCodeBlockBackgroundColor: string; euiCodeBlockColor: string; euiCodeBlockSelectedBackgroundColor: string; euiCodeBlockCommentColor: string; euiCodeBlockSelectorTagColor: string; euiCodeBlockStringColor: string; euiCodeBlockTagColor: string; euiCodeBlockNameColor: string; euiCodeBlockNumberColor: string; euiCodeBlockKeywordColor: string; euiCodeBlockFunctionTitleColor: string; euiCodeBlockTypeColor: string; euiCodeBlockAttributeColor: string; euiCodeBlockSymbolColor: string; euiCodeBlockParamsColor: string; euiCodeBlockMetaColor: string; euiCodeBlockTitleColor: string; euiCodeBlockSectionColor: string; euiCodeBlockAdditionColor: string; euiCodeBlockDeletionColor: string; euiCodeBlockSelectorClassColor: string; euiCodeBlockSelectorIdColor: string; euiPaletteColorBlind: { euiColorVis0: { graphic: string; behindText: string; }; euiColorVis1: { graphic: string; behindText: string; }; euiColorVis2: { graphic: string; behindText: string; }; euiColorVis3: { graphic: string; behindText: string; }; euiColorVis4: { graphic: string; behindText: string; }; euiColorVis5: { graphic: string; behindText: string; }; euiColorVis6: { graphic: string; behindText: string; }; euiColorVis7: { graphic: string; behindText: string; }; euiColorVis8: { graphic: string; behindText: string; }; euiColorVis9: { graphic: string; behindText: string; }; }; euiPaletteColorBlindKeys: string; euiColorVis0: string; euiColorVis1: string; euiColorVis2: string; euiColorVis3: string; euiColorVis4: string; euiColorVis5: string; euiColorVis6: string; euiColorVis7: string; euiColorVis8: string; euiColorVis9: string; euiColorVis0_behindText: string; euiColorVis1_behindText: string; euiColorVis2_behindText: string; euiColorVis3_behindText: string; euiColorVis4_behindText: string; euiColorVis5_behindText: string; euiColorVis6_behindText: string; euiColorVis7_behindText: string; euiColorVis8_behindText: string; euiColorVis9_behindText: string; euiFontWeightLight: number; euiFontWeightRegular: number; euiFontWeightMedium: number; euiFontWeightSemiBold: number; euiFontWeightBold: number; euiCodeFontWeightRegular: number; euiCodeFontWeightBold: number; euiFormMaxWidth: string; euiFormControlHeight: string; euiFormControlCompressedHeight: string; euiFormControlPadding: string; euiFormControlCompressedPadding: string; euiFormControlBorderRadius: string; euiFormControlCompressedBorderRadius: string; euiRadioSize: string; euiCheckBoxSize: string; euiCheckboxBorderRadius: string; euiSwitchHeight: string; euiSwitchWidth: string; euiSwitchThumbSize: string; euiSwitchIconHeight: string; euiSwitchHeightCompressed: string; euiSwitchWidthCompressed: string; euiSwitchThumbSizeCompressed: string; euiSwitchHeightMini: string; euiSwitchWidthMini: string; euiSwitchThumbSizeMini: string; euiFormBackgroundColor: string; euiFormBackgroundDisabledColor: string; euiFormBackgroundReadOnlyColor: string; euiFormBorderOpaqueColor: string; euiFormBorderColor: string; euiFormBorderDisabledColor: string; euiFormCustomControlDisabledIconColor: string; euiFormCustomControlBorderColor: string; euiFormControlDisabledColor: string; euiFormControlBoxShadow: string; euiFormControlPlaceholderText: string; euiFormInputGroupLabelBackground: string; euiFormInputGroupBorder: string; euiSwitchOffColor: string; euiFormControlIconSizes: { small: string; medium: string; large: string; xLarge: string; xxLarge: string; }; euiFormControlLayoutGroupInputHeight: string; euiFormControlLayoutGroupInputCompressedHeight: string; euiFormControlLayoutGroupInputCompressedBorderRadius: string; euiRangeTrackColor: string; euiRangeThumbRadius: string; euiRangeThumbHeight: string; euiRangeThumbWidth: string; euiRangeThumbBorderColor: string; euiRangeTrackWidth: string; euiRangeTrackHeight: string; euiRangeTrackBorderWidth: number; euiRangeTrackBorderColor: string; euiRangeTrackRadius: string; euiRangeDisabledOpacity: number; euiRangeHighlightHeight: string; euiHeaderBackgroundColor: string; euiHeaderDarkBackgroundColor: string; euiHeaderBorderColor: string; euiHeaderBreadcrumbColor: string; euiHeaderHeight: string; euiHeaderChildSize: string; euiHeaderHeightCompensation: string; euiPageDefaultMaxWidth: string; euiPageSidebarMinWidth: string; euiPanelPaddingModifiers: { paddingSmall: string; paddingMedium: string; paddingLarge: string; }; euiPanelBorderRadiusModifiers: { borderRadiusNone: number; borderRadiusMedium: string; }; euiPanelBackgroundColorModifiers: { transparent: string; plain: string; subdued: string; accent: string; primary: string; success: string; warning: string; danger: string; }; euiBreakpoints: { xs: number; s: string; m: string; l: string; xl: string; }; euiBreakpointKeys: string; euiShadowColor: string; euiSize: string; euiSizeXS: string; euiSizeS: string; euiSizeM: string; euiSizeL: string; euiSizeXL: string; euiSizeXXL: string; euiButtonMinWidth: string; euiScrollBar: string; euiScrollBarCorner: string; euiScrollBarCornerThin: string; euiFocusRingColor: string; euiFocusRingAnimStartColor: string; euiFocusRingAnimStartSize: string; euiFocusRingAnimStartSizeLarge: string; euiFocusRingSizeLarge: string; euiFocusRingSize: string; euiFocusTransparency: number; euiFocusTransparencyPercent: string; euiFocusBackgroundColor: string; euiTooltipBackgroundColor: string; euiTooltipBorderColor: string; euiTooltipAnimations: { top: string; left: string; bottom: string; right: string; }; euiFontFamily: string; euiCodeFontFamily: string; euiFontFeatureSettings: string; euiTextScale: string; euiFontSize: string; euiFontSizeXS: string; euiFontSizeS: string; euiFontSizeM: string; euiFontSizeL: string; euiFontSizeXL: string; euiFontSizeXXL: string; euiLineHeight: number; euiBodyLineHeight: number; euiTitles: { xxxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xxs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; xs: { 'font-size': string; 'line-height': string; 'font-weight': number; }; s: { 'font-size': string; 'line-height': string; 'font-weight': number; }; m: { 'font-size': string; 'line-height': string; 'font-weight': number; }; l: { 'font-size': string; 'line-height': string; 'font-weight': number; }; }; euiZLevel0: number; euiZLevel1: number; euiZLevel2: number; euiZLevel3: number; euiZLevel4: number; euiZLevel5: number; euiZLevel6: number; euiZLevel7: number; euiZLevel8: number; euiZLevel9: number; euiZToastList: number; euiZModal: number; euiZMask: number; euiZNavigation: number; euiZContentMenu: number; euiZHeader: number; euiZFlyout: number; euiZMaskBelowHeader: number; euiZContent: number; euiColorGhost: string; euiColorInk: string; euiColorPrimary: string; euiColorAccent: string; euiColorSuccess: string; euiColorWarning: string; euiColorDanger: string; euiColorEmptyShade: string; euiColorLightestShade: string; euiColorLightShade: string; euiColorMediumShade: string; euiColorDarkShade: string; euiColorDarkestShade: string; euiColorFullShade: string; euiPageBackgroundColor: string; euiColorHighlight: string; euiTextColor: string; euiTitleColor: string; euiTextSubduedColor: string; euiColorDisabled: string; euiColorPrimaryText: string; euiColorSuccessText: string; euiColorAccentText: string; euiColorWarningText: string; euiColorDangerText: string; euiColorDisabledText: string; euiLinkColor: string; euiColorChartLines: string; euiColorChartBand: string; euiDatePickerCalendarWidth: string; euiDatePickerPadding: string; euiDatePickerGap: string; euiDatePickerCalendarColumns: number; euiDatePickerButtonSize: string; euiDatePickerMinControlWidth: string; euiDatePickerMaxControlWidth: string; euiButtonDefaultTransparency: number; euiButtonFontWeight: number; euiRangeHighlightColor: string; euiRangeThumbBackgroundColor: string; euiRangeTrackCompressedHeight: string; euiRangeHighlightCompressedHeight: string; euiRangeHeight: string; euiRangeCompressedHeight: string; euiStepStatusColors: { default: string; complete: string; warning: string; danger: string; }; }" ], "path": "src/plugins/kibana_react/common/eui_styled_components.tsx", "deprecated": false, diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 5dc1c70a12e19..79b13332456d4 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: 2022-09-20 +date: 2022-09-21 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 cbde41998f2e9..676f396e38cc2 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: 2022-09-20 +date: 2022-09-21 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 1b919dd1a45b7..97372d71d53fb 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 724ee8dd1b668..4fc56c34842e9 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -4504,7 +4504,17 @@ "signature": [ "((state: P, references?: ", "SavedObjectReference", - "[] | undefined) => T) | undefined" + "[] | undefined, initialContext?: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.VisualizeFieldContext", + "text": "VisualizeFieldContext" + }, + " | ", + "VisualizeEditorContext", + " | undefined) => T) | undefined" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -4540,6 +4550,30 @@ "deprecated": false, "trackAdoption": false, "isRequired": false + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.fromPersistableState.$3", + "type": "CompoundType", + "tags": [], + "label": "initialContext", + "description": [], + "signature": [ + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.VisualizeFieldContext", + "text": "VisualizeFieldContext" + }, + " | ", + "VisualizeEditorContext", + " | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false } ], "returnComment": [] @@ -4642,6 +4676,85 @@ ], "returnComment": [] }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.cloneLayer", + "type": "Function", + "tags": [], + "label": "cloneLayer", + "description": [ + "Reset button on each layer triggers this" + ], + "signature": [ + "((state: T, layerId: string, newLayerId: string, clonedIDsMap: Map) => T) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.cloneLayer.$1", + "type": "Uncategorized", + "tags": [], + "label": "state", + "description": [], + "signature": [ + "T" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.cloneLayer.$2", + "type": "string", + "tags": [], + "label": "layerId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.cloneLayer.$3", + "type": "string", + "tags": [], + "label": "newLayerId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.cloneLayer.$4", + "type": "Object", + "tags": [], + "label": "clonedIDsMap", + "description": [], + "signature": [ + "Map" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "lens", "id": "def-public.Visualization.removeLayer", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 653131ded02e2..3d5eb7fe015f6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 640 | 0 | 553 | 41 | +| 646 | 0 | 558 | 42 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 64f0bdfad6df0..3f990bbcb20d0 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: 2022-09-20 +date: 2022-09-21 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 a31914ec5badf..9e7dc24aae0e2 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.devdocs.json b/api_docs/licensing.devdocs.json index 0b456fa70029f..335c7891795d3 100644 --- a/api_docs/licensing.devdocs.json +++ b/api_docs/licensing.devdocs.json @@ -2142,6 +2142,10 @@ "plugin": "searchprofiler", "path": "x-pack/plugins/searchprofiler/server/plugin.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts" + }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/server/services/license.ts" diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index c9ddbed424930..c16ee014aeeb8 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index ad79875fc4108..619cdab0943f7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index cb04898032b5f..4850104f76366 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: 2022-09-20 +date: 2022-09-21 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 fb9923f8b2d6d..57b107d6beadb 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: 2022-09-20 +date: 2022-09-21 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 3b3b444c80646..90a09544d07e7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 9eacb8772d83d..e430f45966c72 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index ec3b931092bb9..167becc10bb92 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: 2022-09-20 +date: 2022-09-21 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 ec07fb98e351d..5046f23612945 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: 2022-09-20 +date: 2022-09-21 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 e4db7f2310e13..b7f3142a5db26 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: 2022-09-20 +date: 2022-09-21 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 9b47c9ea3d5d1..80dc9cea35aa6 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 25c742a70b12e..9720b4db69b1f 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -738,11 +738,7 @@ }, " | undefined; list: () => string[]; }; selectedAlertId?: string | undefined; } & ", "CommonProps", - " & { as?: \"div\" | undefined; } & _EuiFlyoutProps & Omit, HTMLDivElement>, keyof _EuiFlyoutProps> & Omit, HTMLDivElement>, \"key\" | keyof React.HTMLAttributes | \"css\"> & { ref?: React.RefObject | ((instance: HTMLDivElement | null) => void) | null | undefined; }, \"children\" | \"onError\" | \"hidden\" | \"color\" | \"id\" | \"title\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"as\" | keyof ", - "CommonProps", - " | keyof React.ClassAttributes | keyof _EuiFlyoutProps>, \"children\" | \"onError\" | \"hidden\" | \"color\" | \"id\" | \"alert\" | \"title\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"key\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"as\" | \"css\" | keyof ", - "CommonProps", - " | \"alerts\" | keyof _EuiFlyoutProps | \"isInApp\" | \"observabilityRuleTypeRegistry\" | \"selectedAlertId\"> & { ref?: React.RefObject | ((instance: HTMLDivElement | null) => void) | null | undefined; }> & { readonly _result: ({ alert, alerts, isInApp, observabilityRuleTypeRegistry, onClose, selectedAlertId, }: AlertsFlyoutProps) => JSX.Element | null; }" + " & { as?: \"div\" | undefined; } & _EuiFlyoutProps & Omit, HTMLDivElement>, keyof _EuiFlyoutProps> & Omit, HTMLDivElement>, \"key\" | keyof React.HTMLAttributes | \"css\"> & { ref?: React.RefObject | ((instance: HTMLDivElement | null) => void) | null | undefined; }, \"children\" | \"ref\" | \"type\" | \"onError\" | \"hidden\" | \"color\" | \"id\" | \"className\" | \"size\" | \"title\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"key\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"onClose\" | \"data-test-subj\" | \"css\" | \"as\" | \"paddingSize\" | \"focusTrapProps\" | \"ownFocus\" | \"maxWidth\" | \"hideCloseButton\" | \"closeButtonAriaLabel\" | \"closeButtonProps\" | \"closeButtonPosition\" | \"maskProps\" | \"outsideClickCloses\" | \"side\" | \"pushMinBreakpoint\">, \"children\" | \"type\" | \"onError\" | \"hidden\" | \"color\" | \"id\" | \"alert\" | \"className\" | \"size\" | \"title\" | \"onChange\" | \"onKeyDown\" | \"onClick\" | \"security\" | \"key\" | \"defaultValue\" | \"lang\" | \"defaultChecked\" | \"suppressContentEditableWarning\" | \"suppressHydrationWarning\" | \"accessKey\" | \"contentEditable\" | \"contextMenu\" | \"dir\" | \"draggable\" | \"placeholder\" | \"slot\" | \"spellCheck\" | \"style\" | \"tabIndex\" | \"translate\" | \"radioGroup\" | \"role\" | \"about\" | \"datatype\" | \"inlist\" | \"prefix\" | \"property\" | \"resource\" | \"typeof\" | \"vocab\" | \"autoCapitalize\" | \"autoCorrect\" | \"autoSave\" | \"itemProp\" | \"itemScope\" | \"itemType\" | \"itemID\" | \"itemRef\" | \"results\" | \"unselectable\" | \"inputMode\" | \"is\" | \"aria-activedescendant\" | \"aria-atomic\" | \"aria-autocomplete\" | \"aria-busy\" | \"aria-checked\" | \"aria-colcount\" | \"aria-colindex\" | \"aria-colspan\" | \"aria-controls\" | \"aria-current\" | \"aria-describedby\" | \"aria-details\" | \"aria-disabled\" | \"aria-dropeffect\" | \"aria-errormessage\" | \"aria-expanded\" | \"aria-flowto\" | \"aria-grabbed\" | \"aria-haspopup\" | \"aria-hidden\" | \"aria-invalid\" | \"aria-keyshortcuts\" | \"aria-label\" | \"aria-labelledby\" | \"aria-level\" | \"aria-live\" | \"aria-modal\" | \"aria-multiline\" | \"aria-multiselectable\" | \"aria-orientation\" | \"aria-owns\" | \"aria-placeholder\" | \"aria-posinset\" | \"aria-pressed\" | \"aria-readonly\" | \"aria-relevant\" | \"aria-required\" | \"aria-roledescription\" | \"aria-rowcount\" | \"aria-rowindex\" | \"aria-rowspan\" | \"aria-selected\" | \"aria-setsize\" | \"aria-sort\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"aria-valuetext\" | \"dangerouslySetInnerHTML\" | \"onCopy\" | \"onCopyCapture\" | \"onCut\" | \"onCutCapture\" | \"onPaste\" | \"onPasteCapture\" | \"onCompositionEnd\" | \"onCompositionEndCapture\" | \"onCompositionStart\" | \"onCompositionStartCapture\" | \"onCompositionUpdate\" | \"onCompositionUpdateCapture\" | \"onFocus\" | \"onFocusCapture\" | \"onBlur\" | \"onBlurCapture\" | \"onChangeCapture\" | \"onBeforeInput\" | \"onBeforeInputCapture\" | \"onInput\" | \"onInputCapture\" | \"onReset\" | \"onResetCapture\" | \"onSubmit\" | \"onSubmitCapture\" | \"onInvalid\" | \"onInvalidCapture\" | \"onLoad\" | \"onLoadCapture\" | \"onErrorCapture\" | \"onKeyDownCapture\" | \"onKeyPress\" | \"onKeyPressCapture\" | \"onKeyUp\" | \"onKeyUpCapture\" | \"onAbort\" | \"onAbortCapture\" | \"onCanPlay\" | \"onCanPlayCapture\" | \"onCanPlayThrough\" | \"onCanPlayThroughCapture\" | \"onDurationChange\" | \"onDurationChangeCapture\" | \"onEmptied\" | \"onEmptiedCapture\" | \"onEncrypted\" | \"onEncryptedCapture\" | \"onEnded\" | \"onEndedCapture\" | \"onLoadedData\" | \"onLoadedDataCapture\" | \"onLoadedMetadata\" | \"onLoadedMetadataCapture\" | \"onLoadStart\" | \"onLoadStartCapture\" | \"onPause\" | \"onPauseCapture\" | \"onPlay\" | \"onPlayCapture\" | \"onPlaying\" | \"onPlayingCapture\" | \"onProgress\" | \"onProgressCapture\" | \"onRateChange\" | \"onRateChangeCapture\" | \"onSeeked\" | \"onSeekedCapture\" | \"onSeeking\" | \"onSeekingCapture\" | \"onStalled\" | \"onStalledCapture\" | \"onSuspend\" | \"onSuspendCapture\" | \"onTimeUpdate\" | \"onTimeUpdateCapture\" | \"onVolumeChange\" | \"onVolumeChangeCapture\" | \"onWaiting\" | \"onWaitingCapture\" | \"onAuxClick\" | \"onAuxClickCapture\" | \"onClickCapture\" | \"onContextMenu\" | \"onContextMenuCapture\" | \"onDoubleClick\" | \"onDoubleClickCapture\" | \"onDrag\" | \"onDragCapture\" | \"onDragEnd\" | \"onDragEndCapture\" | \"onDragEnter\" | \"onDragEnterCapture\" | \"onDragExit\" | \"onDragExitCapture\" | \"onDragLeave\" | \"onDragLeaveCapture\" | \"onDragOver\" | \"onDragOverCapture\" | \"onDragStart\" | \"onDragStartCapture\" | \"onDrop\" | \"onDropCapture\" | \"onMouseDown\" | \"onMouseDownCapture\" | \"onMouseEnter\" | \"onMouseLeave\" | \"onMouseMove\" | \"onMouseMoveCapture\" | \"onMouseOut\" | \"onMouseOutCapture\" | \"onMouseOver\" | \"onMouseOverCapture\" | \"onMouseUp\" | \"onMouseUpCapture\" | \"onSelect\" | \"onSelectCapture\" | \"onTouchCancel\" | \"onTouchCancelCapture\" | \"onTouchEnd\" | \"onTouchEndCapture\" | \"onTouchMove\" | \"onTouchMoveCapture\" | \"onTouchStart\" | \"onTouchStartCapture\" | \"onPointerDown\" | \"onPointerDownCapture\" | \"onPointerMove\" | \"onPointerMoveCapture\" | \"onPointerUp\" | \"onPointerUpCapture\" | \"onPointerCancel\" | \"onPointerCancelCapture\" | \"onPointerEnter\" | \"onPointerEnterCapture\" | \"onPointerLeave\" | \"onPointerLeaveCapture\" | \"onPointerOver\" | \"onPointerOverCapture\" | \"onPointerOut\" | \"onPointerOutCapture\" | \"onGotPointerCapture\" | \"onGotPointerCaptureCapture\" | \"onLostPointerCapture\" | \"onLostPointerCaptureCapture\" | \"onScroll\" | \"onScrollCapture\" | \"onWheel\" | \"onWheelCapture\" | \"onAnimationStart\" | \"onAnimationStartCapture\" | \"onAnimationEnd\" | \"onAnimationEndCapture\" | \"onAnimationIteration\" | \"onAnimationIterationCapture\" | \"onTransitionEnd\" | \"onTransitionEndCapture\" | \"onClose\" | \"data-test-subj\" | \"css\" | \"as\" | \"paddingSize\" | \"focusTrapProps\" | \"ownFocus\" | \"alerts\" | \"maxWidth\" | \"hideCloseButton\" | \"closeButtonAriaLabel\" | \"closeButtonProps\" | \"closeButtonPosition\" | \"maskProps\" | \"outsideClickCloses\" | \"side\" | \"pushMinBreakpoint\" | \"isInApp\" | \"observabilityRuleTypeRegistry\" | \"selectedAlertId\"> & { ref?: React.RefObject | ((instance: HTMLDivElement | null) => void) | null | undefined; }> & { readonly _result: ({ alert, alerts, isInApp, observabilityRuleTypeRegistry, onClose, selectedAlertId, }: AlertsFlyoutProps) => JSX.Element | null; }" ], "path": "x-pack/plugins/observability/public/index.ts", "deprecated": false, @@ -7717,13 +7713,35 @@ "label": "ObservabilityAPIReturnType", "description": [], "signature": [ - "{ \"POST /api/observability/slos\"?: ", + "{ \"DELETE /api/observability/slos/{id}\"?: ", + "ServerRoute", + "<\"DELETE /api/observability/slos/{id}\", ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ id: ", + "StringC", + "; }>; }>, ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteHandlerResources", + "text": "ObservabilityRouteHandlerResources" + }, + ", void, ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteCreateOptions", + "text": "ObservabilityRouteCreateOptions" + }, + "> | undefined; \"POST /api/observability/slos\"?: ", "ServerRoute", "<\"POST /api/observability/slos\", ", "TypeC", "<{ body: ", - "IntersectionC", - "<[", "TypeC", "<{ name: ", "StringC", @@ -7821,13 +7839,7 @@ "TypeC", "<{ target: ", "NumberC", - "; }>; }>, ", - "PartialC", - "<{ settings: ", - "PartialC", - "<{ destination_index: ", - "StringC", - "; }>; }>]>; }>, ", + "; }>; }>; }>, ", { "pluginId": "observability", "scope": "server", @@ -7905,13 +7917,35 @@ "label": "ObservabilityServerRouteRepository", "description": [], "signature": [ - "{ \"POST /api/observability/slos\"?: ", + "{ \"DELETE /api/observability/slos/{id}\"?: ", + "ServerRoute", + "<\"DELETE /api/observability/slos/{id}\", ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ id: ", + "StringC", + "; }>; }>, ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteHandlerResources", + "text": "ObservabilityRouteHandlerResources" + }, + ", void, ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteCreateOptions", + "text": "ObservabilityRouteCreateOptions" + }, + "> | undefined; \"POST /api/observability/slos\"?: ", "ServerRoute", "<\"POST /api/observability/slos\", ", "TypeC", "<{ body: ", - "IntersectionC", - "<[", "TypeC", "<{ name: ", "StringC", @@ -8009,13 +8043,7 @@ "TypeC", "<{ target: ", "NumberC", - "; }>; }>, ", - "PartialC", - "<{ settings: ", - "PartialC", - "<{ destination_index: ", - "StringC", - "; }>; }>]>; }>, ", + "; }>; }>; }>, ", { "pluginId": "observability", "scope": "server", @@ -9450,6 +9478,126 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics", + "type": "Object", + "tags": [], + "label": "[enableAwsLambdaMetrics]", + "description": [], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.category", + "type": "Array", + "tags": [], + "label": "category", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + "Type", + "" + ], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.value", + "type": "boolean", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "true" + ], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.requiresPageReload", + "type": "boolean", + "tags": [], + "label": "requiresPageReload", + "description": [], + "signature": [ + "true" + ], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"boolean\"" + ], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableAwsLambdaMetrics.showInLabs", + "type": "boolean", + "tags": [], + "label": "showInLabs", + "description": [], + "signature": [ + "true" + ], + "path": "x-pack/plugins/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + } + ] } ], "initialIsOpen": false @@ -9879,6 +10027,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "observability", + "id": "def-common.enableAwsLambdaMetrics", + "type": "string", + "tags": [], + "label": "enableAwsLambdaMetrics", + "description": [], + "signature": [ + "\"observability:enableAwsLambdaMetrics\"" + ], + "path": "x-pack/plugins/observability/common/ui_settings_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "observability", "id": "def-common.enableComparisonByDefault", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index f808ef503a4c0..e4a65ba5f33e7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Observability UI](https://github.com/orgs/elastic/teams/observability-u | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 509 | 2 | 505 | 30 | +| 519 | 2 | 515 | 30 | ## Client diff --git a/api_docs/osquery.devdocs.json b/api_docs/osquery.devdocs.json index 8d45fc77730ef..bcaaa466f6ca5 100644 --- a/api_docs/osquery.devdocs.json +++ b/api_docs/osquery.devdocs.json @@ -48,6 +48,39 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.OsqueryResults", + "type": "Function", + "tags": [], + "label": "OsqueryResults", + "description": [], + "signature": [ + "(props: ", + "OsqueryActionResultsProps", + ") => JSX.Element" + ], + "path": "x-pack/plugins/osquery/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.OsqueryResults.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "OsqueryActionResultsProps" + ], + "path": "x-pack/plugins/osquery/public/shared_components/lazy_osquery_results.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "osquery", "id": "def-public.OsqueryPluginStart.LiveQueryField", @@ -106,6 +139,53 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.fetchInstallationStatus", + "type": "Function", + "tags": [], + "label": "fetchInstallationStatus", + "description": [], + "signature": [ + "() => { loading: boolean; disabled: boolean; permissionDenied: boolean; }" + ], + "path": "x-pack/plugins/osquery/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.OsqueryResponseActionTypeForm", + "type": "Function", + "tags": [], + "label": "OsqueryResponseActionTypeForm", + "description": [], + "signature": [ + "(props: LazyOsqueryActionParamsFormProps) => JSX.Element" + ], + "path": "x-pack/plugins/osquery/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.OsqueryResponseActionTypeForm.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "LazyOsqueryActionParamsFormProps" + ], + "path": "x-pack/plugins/osquery/public/shared_components/lazy_osquery_action_params_form.tsx", + "deprecated": false, + "trackAdoption": false + } + ] } ], "lifecycle": "start", @@ -129,7 +209,40 @@ "path": "x-pack/plugins/osquery/server/types.ts", "deprecated": false, "trackAdoption": false, - "children": [], + "children": [ + { + "parentPluginId": "osquery", + "id": "def-server.OsqueryPluginSetup.osqueryCreateAction", + "type": "Function", + "tags": [], + "label": "osqueryCreateAction", + "description": [], + "signature": [ + "(payload: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; }; version: string; platform: string; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; } | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }) => void" + ], + "path": "x-pack/plugins/osquery/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "osquery", + "id": "def-server.OsqueryPluginSetup.osqueryCreateAction.$1", + "type": "Object", + "tags": [], + "label": "payload", + "description": [], + "signature": [ + "{ agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; }; version: string; platform: string; }[] | { [x: string]: { query: string; id: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; saved_query_id: string | undefined; }; } | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }" + ], + "path": "x-pack/plugins/osquery/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], "lifecycle": "setup", "initialIsOpen": true }, diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 39fb0bbcd0e5d..f87b8903f184c 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Security asset management](https://github.com/orgs/elastic/teams/securi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 14 | 0 | 14 | 2 | +| 21 | 0 | 21 | 3 | ## Client diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index f579ba9e630fb..9bc3e41f6b9e1 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: 2022-09-20 +date: 2022-09-21 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 | |--------------|----------|------------------------| -| 460 | 386 | 38 | +| 462 | 388 | 38 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 31149 | 179 | 20873 | 982 | +| 31334 | 180 | 21000 | 980 | ## Plugin Directory @@ -31,17 +31,18 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 36 | 1 | 32 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 9 | 0 | 0 | 2 | | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 370 | 0 | 361 | 22 | -| | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 38 | 0 | 38 | 52 | +| | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 38 | 0 | 38 | 51 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 80 | 1 | 71 | 2 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Canvas application to Kibana | 9 | 0 | 8 | 3 | | | [ResponseOps](https://github.com/orgs/elastic/teams/response-ops) | The Case management system in Kibana | 87 | 0 | 71 | 28 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 264 | 2 | 249 | 9 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 29 | 0 | 24 | 0 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/@elastic/kibana-core) | Provides the necessary APIs to implement A/B testing scenarios, fetching the variations in configuration and reporting back metrics to track conversion rates of the experiments. | 16 | 0 | 0 | 0 | | | [Cloud Security Posture](https://github.com/orgs/elastic/teams/cloud-posture-security) | The cloud security posture plugin | 18 | 0 | 2 | 3 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 212 | 0 | 204 | 7 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2657 | 0 | 45 | 2 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2684 | 0 | 45 | 0 | | crossClusterReplication | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 103 | 0 | 84 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 144 | 0 | 139 | 10 | @@ -53,7 +54,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 966 | 0 | 208 | 1 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 28 | 3 | 24 | 1 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 96 | 0 | 79 | 4 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 97 | 0 | 80 | 4 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds embeddables service to Kibana | 515 | 0 | 415 | 4 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | @@ -80,7 +81,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 5 | 249 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | | | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 240 | 0 | 6 | 2 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 974 | 3 | 874 | 17 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 986 | 3 | 886 | 17 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -100,7 +101,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | kibanaUsageCollection | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 615 | 3 | 418 | 9 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | 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. | 640 | 0 | 553 | 41 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | 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. | 646 | 0 | 558 | 42 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | @@ -114,15 +115,15 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Stack Monitoring](https://github.com/orgs/elastic/teams/stack-monitoring-ui) | - | 9 | 0 | 9 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 34 | 0 | 34 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | -| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 509 | 2 | 505 | 30 | -| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 14 | 0 | 14 | 2 | +| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 519 | 2 | 515 | 30 | +| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 21 | 0 | 21 | 3 | | painlessLab | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 243 | 2 | 187 | 12 | | | [profiling](https://github.com/orgs/elastic/teams/profiling-ui) | - | 14 | 1 | 14 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | | | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 36 | 0 | 16 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 21 | 0 | 21 | 0 | -| | [RAC](https://github.com/orgs/elastic/teams/rac) | - | 215 | 0 | 187 | 11 | +| | [RAC](https://github.com/orgs/elastic/teams/rac) | - | 230 | 0 | 202 | 10 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 24 | 0 | 19 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 193 | 2 | 152 | 5 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 16 | 0 | 16 | 0 | @@ -134,7 +135,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 27 | 0 | 8 | 4 | | searchprofiler | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 247 | 0 | 90 | 0 | -| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 54 | 0 | 53 | 22 | +| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 55 | 0 | 54 | 23 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds URL Service and sharing capabilities to Kibana | 114 | 0 | 55 | 10 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 22 | 1 | 22 | 1 | @@ -151,9 +152,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 450 | 1 | 344 | 33 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [Kibana Localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 428 | 0 | 407 | 46 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 437 | 1 | 416 | 45 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 132 | 0 | 91 | 11 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 205 | 0 | 142 | 9 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 206 | 0 | 142 | 9 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 61 | 0 | 59 | 2 | | | [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-services) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 122 | 2 | 96 | 16 | | upgradeAssistant | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | @@ -174,7 +175,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the vega visualization. Is the elastic version of vega and vega-lite libraries. | 2 | 0 | 2 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the vislib visualizations. These are the classical area/line/bar, pie, gauge/goal and heatmap charts. We want to replace them with elastic-charts. | 26 | 0 | 25 | 1 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the new xy-axis chart using the elastic-charts library, which will eventually replace the vislib xy-axis charts including bar, area, and line. | 53 | 0 | 50 | 5 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 611 | 12 | 582 | 14 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 630 | 12 | 601 | 14 | | watcher | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | ## Package Directory @@ -295,9 +296,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 5 | 0 | 0 | 0 | | | Kibana Core | - | 6 | 0 | 6 | 0 | | | Kibana Core | - | 2 | 0 | 2 | 0 | -| | Kibana Core | - | 94 | 1 | 66 | 0 | -| | Kibana Core | - | 289 | 1 | 126 | 0 | -| | Kibana Core | - | 68 | 0 | 49 | 0 | +| | Kibana Core | - | 106 | 1 | 75 | 0 | +| | Kibana Core | - | 308 | 1 | 137 | 0 | +| | Kibana Core | - | 71 | 0 | 51 | 0 | | | Kibana Core | - | 6 | 0 | 6 | 0 | | | Kibana Core | - | 37 | 0 | 31 | 1 | | | Kibana Core | - | 4 | 0 | 4 | 0 | @@ -310,7 +311,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 100 | 0 | 74 | 43 | | | Kibana Core | - | 12 | 0 | 12 | 0 | | | Kibana Core | - | 225 | 0 | 82 | 0 | -| | Kibana Core | - | 66 | 0 | 66 | 4 | +| | Kibana Core | - | 69 | 0 | 69 | 4 | | | Kibana Core | - | 14 | 0 | 13 | 0 | | | Kibana Core | - | 99 | 1 | 86 | 0 | | | Kibana Core | - | 12 | 0 | 2 | 0 | @@ -330,7 +331,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 27 | 1 | 13 | 0 | | | Kibana Core | - | 28 | 1 | 27 | 1 | | | Kibana Core | - | 6 | 0 | 6 | 0 | -| | Kibana Core | - | 146 | 0 | 135 | 0 | +| | Kibana Core | - | 153 | 0 | 142 | 0 | | | Kibana Core | - | 8 | 0 | 8 | 2 | | | Kibana Core | - | 7 | 0 | 7 | 0 | | | [Owner missing] | - | 13 | 0 | 7 | 0 | @@ -346,6 +347,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 27 | 0 | 14 | 1 | | | Kibana Core | - | 7 | 0 | 3 | 0 | | | [Owner missing] | - | 222 | 1 | 168 | 12 | +| | Kibana Core | - | 11 | 0 | 11 | 0 | | | [Owner missing] | - | 2 | 0 | 1 | 0 | | | [Owner missing] | - | 20 | 0 | 16 | 0 | | | [Owner missing] | - | 2 | 0 | 0 | 0 | @@ -365,7 +367,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 8 | 0 | 8 | 0 | | | [Owner missing] | - | 6 | 0 | 1 | 1 | | | [Owner missing] | - | 534 | 1 | 1 | 0 | -| | Machine Learning UI | This package includes utility functions related to creating elasticsearch aggregation queries, data manipulation and verification. | 58 | 2 | 39 | 3 | +| | Machine Learning UI | This package includes utility functions related to creating elasticsearch aggregation queries, data manipulation and verification. | 64 | 2 | 44 | 3 | | | Machine Learning UI | A type guard to check record like object structures. | 3 | 0 | 2 | 0 | | | Machine Learning UI | Creates a deterministic number based hash out of a string. | 2 | 0 | 1 | 0 | | | [Owner missing] | - | 55 | 0 | 55 | 2 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index b7d546ea5bb4c..5c1ba3fbe59be 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 018931d925b07..aa3a5a11aa480 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index b74c2aad10f9a..c20d0362bae48 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: 2022-09-20 +date: 2022-09-21 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 ad3ea82997456..b58df3eacde86 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: 2022-09-20 +date: 2022-09-21 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 b816147f94c89..8f47f3dda1591 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.devdocs.json b/api_docs/rule_registry.devdocs.json index 8d63050c8a9b0..424057fd0db70 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -411,7 +411,13 @@ "description": [], "signature": [ "({ indices, metaFields, allowNoIndex, }: { indices: string[]; metaFields: string[]; allowNoIndex: boolean; }) => Promise<", - "BrowserFields", + { + "pluginId": "ruleRegistry", + "scope": "common", + "docId": "kibRuleRegistryPluginApi", + "section": "def-common.BrowserFields", + "text": "BrowserFields" + }, ">" ], "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", @@ -3985,6 +3991,200 @@ } ], "interfaces": [ + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField", + "type": "Interface", + "tags": [], + "label": "BrowserField", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.aggregatable", + "type": "boolean", + "tags": [], + "label": "aggregatable", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.category", + "type": "string", + "tags": [], + "label": "category", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.description", + "type": "CompoundType", + "tags": [], + "label": "description", + "description": [], + "signature": [ + "string | null | undefined" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.example", + "type": "CompoundType", + "tags": [], + "label": "example", + "description": [], + "signature": [ + "string | number | null | undefined" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.fields", + "type": "Object", + "tags": [], + "label": "fields", + "description": [], + "signature": [ + "{ readonly [x: string]: Partial<", + { + "pluginId": "ruleRegistry", + "scope": "common", + "docId": "kibRuleRegistryPluginApi", + "section": "def-common.BrowserField", + "text": "BrowserField" + }, + ">; }" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.format", + "type": "string", + "tags": [], + "label": "format", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.indexes", + "type": "Array", + "tags": [], + "label": "indexes", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.searchable", + "type": "boolean", + "tags": [], + "label": "searchable", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.subType", + "type": "CompoundType", + "tags": [], + "label": "subType", + "description": [], + "signature": [ + "IFieldSubType", + " | undefined" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.readFromDocValues", + "type": "boolean", + "tags": [], + "label": "readFromDocValues", + "description": [], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserField.runtimeField", + "type": "Object", + "tags": [], + "label": "runtimeField", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + }, + " | undefined" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "ruleRegistry", "id": "def-common.RuleRegistrySearchRequestPagination", @@ -4039,6 +4239,29 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "ruleRegistry", + "id": "def-common.BrowserFields", + "type": "Type", + "tags": [], + "label": "BrowserFields", + "description": [], + "signature": [ + "{ [x: string]: Partial<", + { + "pluginId": "ruleRegistry", + "scope": "common", + "docId": "kibRuleRegistryPluginApi", + "section": "def-common.BrowserField", + "text": "BrowserField" + }, + ">; }" + ], + "path": "x-pack/plugins/rule_registry/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "ruleRegistry", "id": "def-common.ParsedTechnicalFields", diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 10e3e605e3dbe..1e009c82de870 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; @@ -21,7 +21,7 @@ Contact [RAC](https://github.com/orgs/elastic/teams/rac) for questions regarding | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 215 | 0 | 187 | 11 | +| 230 | 0 | 202 | 10 | ## Server diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index aed78d453b32a..bf84cc9fa0b90 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: 2022-09-20 +date: 2022-09-21 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 f03ea7d006a30..8fb8ea0d3c2b7 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: 2022-09-20 +date: 2022-09-21 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 b2785bd5fedfc..c9b068a72abff 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.devdocs.json b/api_docs/saved_objects_management.devdocs.json index 3c4ff5fc143a3..1f64f3bea1abe 100644 --- a/api_docs/saved_objects_management.devdocs.json +++ b/api_docs/saved_objects_management.devdocs.json @@ -310,7 +310,11 @@ "section": "def-public.SavedObjectsManagementRecord", "text": "SavedObjectsManagementRecord" }, - "; headers?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; height?: string | number | undefined; width?: string | undefined; readOnly?: boolean | undefined; align?: ", + "; headers?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", + "Interpolation", + "<", + "Theme", + ">; height?: string | number | undefined; width?: string | undefined; readOnly?: boolean | undefined; align?: ", "HorizontalAlignment", " | undefined; abbr?: string | undefined; footer?: string | React.ReactElement> | ((props: ", "EuiTableFooterProps", diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index e2f4168974e43..a93096c35f284 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index a354225c86402..5c0f411010392 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 50182897c2fbd..9eccbd9ed489d 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: 2022-09-20 +date: 2022-09-21 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 df41afa0216df..6f35997066953 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: 2022-09-20 +date: 2022-09-21 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 f3de4702d11b1..e66c9d7da18f5 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: 2022-09-20 +date: 2022-09-21 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 7bcef95c29df0..a09ddaab21afb 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 9f6f7650337cb..fedcffb1b25d5 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 5827c20db016b..a67fa886963b7 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -64,7 +64,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; readonly policyResponseInFleetEnabled: boolean; readonly threatIntelligenceEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly responseActionsConsoleEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; readonly policyResponseInFleetEnabled: boolean; readonly threatIntelligenceEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly responseActionsConsoleEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, @@ -1080,6 +1080,20 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "securitySolution", + "id": "def-server.SecuritySolutionApiRequestHandlerContext.getQueryRuleAdditionalOptions", + "type": "Object", + "tags": [], + "label": "getQueryRuleAdditionalOptions", + "description": [], + "signature": [ + "CreateQueryRuleAdditionalOptions" + ], + "path": "x-pack/plugins/security_solution/server/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1095,7 +1109,7 @@ "label": "ConfigType", "description": [], "signature": [ - "Readonly<{} & { signalsIndex: string; maxRuleImportExportSize: number; maxRuleImportPayloadBytes: number; maxTimelineImportExportSize: number; maxTimelineImportPayloadBytes: number; alertMergeStrategy: \"allFields\" | \"missingFields\" | \"noFields\"; alertIgnoreFields: string[]; enableExperimental: string[]; packagerTaskInterval: string; prebuiltRulesFromFileSystem: boolean; prebuiltRulesFromSavedObjects: boolean; }> & { experimentalFeatures: Readonly<{ tGridEnabled: boolean; tGridEventRenderedViewEnabled: boolean; excludePoliciesInFilterEnabled: boolean; kubernetesEnabled: boolean; disableIsolationUIPendingStatuses: boolean; pendingActionResponsesWithAck: boolean; policyListEnabled: boolean; policyResponseInFleetEnabled: boolean; threatIntelligenceEnabled: boolean; previewTelemetryUrlEnabled: boolean; responseActionsConsoleEnabled: boolean; insightsRelatedAlertsByProcessAncestry: boolean; extendedRuleExecutionLoggingEnabled: boolean; socTrendsEnabled: boolean; }>; }" + "Readonly<{} & { signalsIndex: string; maxRuleImportExportSize: number; maxRuleImportPayloadBytes: number; maxTimelineImportExportSize: number; maxTimelineImportPayloadBytes: number; alertMergeStrategy: \"allFields\" | \"missingFields\" | \"noFields\"; alertIgnoreFields: string[]; enableExperimental: string[]; packagerTaskInterval: string; prebuiltRulesFromFileSystem: boolean; prebuiltRulesFromSavedObjects: boolean; }> & { experimentalFeatures: Readonly<{ tGridEnabled: boolean; tGridEventRenderedViewEnabled: boolean; excludePoliciesInFilterEnabled: boolean; kubernetesEnabled: boolean; disableIsolationUIPendingStatuses: boolean; pendingActionResponsesWithAck: boolean; policyListEnabled: boolean; policyResponseInFleetEnabled: boolean; threatIntelligenceEnabled: boolean; previewTelemetryUrlEnabled: boolean; responseActionsConsoleEnabled: boolean; insightsRelatedAlertsByProcessAncestry: boolean; extendedRuleExecutionLoggingEnabled: boolean; socTrendsEnabled: boolean; responseActionsEnabled: boolean; }>; }" ], "path": "x-pack/plugins/security_solution/server/config.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 5022716224980..60d6c667f7c91 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Security solution](https://github.com/orgs/elastic/teams/security-solut | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 54 | 0 | 53 | 22 | +| 55 | 0 | 54 | 23 | ## Client diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 25ab4bd3d6c53..408b96cf182b1 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: 2022-09-20 +date: 2022-09-21 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 017d32c37d4f7..e0a7355048af7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index c6c6e0cc46148..e4f72340d087e 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: 2022-09-20 +date: 2022-09-21 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 1ffb54e68ed96..98cb1380a3503 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: 2022-09-20 +date: 2022-09-21 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 d50a8500a951d..0d23909034ae8 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: 2022-09-20 +date: 2022-09-21 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 dcbc38512094c..8b250938595f7 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index de40bcf02dc92..d33ad32bec354 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: 2022-09-20 +date: 2022-09-21 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 fd689d3934388..d170306872998 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: 2022-09-20 +date: 2022-09-21 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 f1d4653b9dc81..6f9d668fb6cea 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 89a20be1cb5fa..ed6b7e61717c5 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index b945f23a74e3a..7ad0996faeb49 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: 2022-09-20 +date: 2022-09-21 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 d2593dcd4c562..341dca64a770b 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: 2022-09-20 +date: 2022-09-21 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 4bd6794b21f76..ef634330a3c39 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: 2022-09-20 +date: 2022-09-21 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 4868243b57664..d4370cbd83025 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 77ded4f84172b..42809d2bac92c 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -2339,6 +2339,150 @@ "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.browserFields", + "type": "Any", + "tags": [], + "label": "browserFields", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onToggleColumn", + "type": "Function", + "tags": [], + "label": "onToggleColumn", + "description": [], + "signature": [ + "(columnId: string) => void" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onToggleColumn.$1", + "type": "string", + "tags": [], + "label": "columnId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onResetColumns", + "type": "Function", + "tags": [], + "label": "onResetColumns", + "description": [], + "signature": [ + "() => void" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onColumnsChange", + "type": "Function", + "tags": [], + "label": "onColumnsChange", + "description": [], + "signature": [ + "(columns: ", + "EuiDataGridColumn", + "[], visibleColumns: string[]) => void" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onColumnsChange.$1", + "type": "Array", + "tags": [], + "label": "columns", + "description": [], + "signature": [ + "EuiDataGridColumn", + "[]" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onColumnsChange.$2", + "type": "Array", + "tags": [], + "label": "visibleColumns", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onChangeVisibleColumns", + "type": "Function", + "tags": [], + "label": "onChangeVisibleColumns", + "description": [], + "signature": [ + "(newColumns: string[]) => void" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.AlertsTableProps.onChangeVisibleColumns.$1", + "type": "Array", + "tags": [], + "label": "newColumns", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -2766,8 +2910,14 @@ "A map of categoryId -> metadata about the fields in that category" ], "signature": [ - "{ readonly [x: string]: Partial<", - "BrowserField", + "{ [x: string]: Partial<", + { + "pluginId": "ruleRegistry", + "scope": "common", + "docId": "kibRuleRegistryPluginApi", + "section": "def-common.BrowserField", + "text": "BrowserField" + }, ">; }" ], "path": "x-pack/plugins/triggers_actions_ui/public/application/sections/field_browser/types.ts", diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index b81484ae1426f..6c8003d4f5dfd 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 428 | 0 | 407 | 46 | +| 437 | 1 | 416 | 45 | ## Client diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 8b6617ccdb0c0..146259f72f7bb 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.devdocs.json b/api_docs/ui_actions_enhanced.devdocs.json index f4fbda2b1815f..923b69011b532 100644 --- a/api_docs/ui_actions_enhanced.devdocs.json +++ b/api_docs/ui_actions_enhanced.devdocs.json @@ -2854,7 +2854,7 @@ "tags": [], "label": "getDisplayName", "description": [ - "\nShould return an internationalized name of the drilldown, which will be\ndisplayed to the user." + "\nShould return an internationalized name of the drilldown, which will be\ndisplayed to the user as the name of drilldown factory when configuring a drilldown." ], "signature": [ "() => string" @@ -2865,6 +2865,45 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "uiActionsEnhanced", + "id": "def-public.DrilldownDefinition.actionMenuItem", + "type": "Function", + "tags": [], + "label": "actionMenuItem", + "description": [ + "\nName of the drilldown instance displayed to the user at the moment of\ndrilldown execution. Should be internationalized." + ], + "signature": [ + { + "pluginId": "kibanaUtils", + "scope": "common", + "docId": "kibKibanaUtilsPluginApi", + "section": "def-common.UiComponent", + "text": "UiComponent" + }, + "<{ config: Omit<", + { + "pluginId": "uiActionsEnhanced", + "scope": "common", + "docId": "kibUiActionsEnhancedPluginApi", + "section": "def-common.SerializedAction", + "text": "SerializedAction" + }, + ", \"factoryId\">; context: ExecutionContext | ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.ActionExecutionContext", + "text": "ActionExecutionContext" + }, + "; }> | undefined" + ], + "path": "src/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "uiActionsEnhanced", "id": "def-public.DrilldownDefinition.isCompatible", diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index d9207909cfb57..427db15b1b3ad 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 205 | 0 | 142 | 9 | +| 206 | 0 | 142 | 9 | ## Client diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index f64afc9f9b339..4d489503da198 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index eb27791b68225..67b3d84096fc4 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: 2022-09-20 +date: 2022-09-21 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 307924444436a..9d8991e0ea45d 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 4718f11d57d79..46e7ae60e2614 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: 2022-09-20 +date: 2022-09-21 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 474edc06dbf7c..a6dfb697d8c5a 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: 2022-09-20 +date: 2022-09-21 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 5ff9b1833cfb0..c281ebdbd88df 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: 2022-09-20 +date: 2022-09-21 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 63eab9d578d13..800fbabeaf203 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: 2022-09-20 +date: 2022-09-21 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 944b8314efe6d..f574152d0a191 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: 2022-09-20 +date: 2022-09-21 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 0971a99c4c319..625d6628b13cf 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: 2022-09-20 +date: 2022-09-21 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 2e9c36c73eb9a..6bd851dad3a56 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: 2022-09-20 +date: 2022-09-21 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 0c0d6e2b147ce..8c8bad65b3868 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: 2022-09-20 +date: 2022-09-21 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 990c37c3170ae..9037c2163f3d5 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: 2022-09-20 +date: 2022-09-21 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 d7a2655939277..69e98952c0f79 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: 2022-09-20 +date: 2022-09-21 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 d0388d1f5e605..7f049ea5d969d 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: 2022-09-20 +date: 2022-09-21 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 851682c10efa5..83c0958ab36ce 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: 2022-09-20 +date: 2022-09-21 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 de09fefa94f16..51b71c88e6a10 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.devdocs.json b/api_docs/visualizations.devdocs.json index 33b99385c989a..f4ce7d07d4c8f 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -7066,6 +7066,62 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.isAnnotationsLayer", + "type": "Function", + "tags": [], + "label": "isAnnotationsLayer", + "description": [], + "signature": [ + "(layer: Pick<", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.XYLayerConfig", + "text": "XYLayerConfig" + }, + ", \"layerType\">) => layer is ", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.XYAnnotationsLayerConfig", + "text": "XYAnnotationsLayerConfig" + } + ], + "path": "src/plugins/visualizations/common/convert_to_lens/utils.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.isAnnotationsLayer.$1", + "type": "Object", + "tags": [], + "label": "layer", + "description": [], + "signature": [ + "Pick<", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.XYLayerConfig", + "text": "XYLayerConfig" + }, + ", \"layerType\">" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.isVisDimension", @@ -7970,6 +8026,155 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig", + "type": "Interface", + "tags": [], + "label": "EventAnnotationConfig", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.filter", + "type": "CompoundType", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "{ type: \"kibana_query\"; } & ", + "Query" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.timeField", + "type": "string", + "tags": [], + "label": "timeField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.extraFields", + "type": "Array", + "tags": [], + "label": "extraFields", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.label", + "type": "string", + "tags": [], + "label": "label", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.color", + "type": "string", + "tags": [], + "label": "color", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.isHidden", + "type": "CompoundType", + "tags": [], + "label": "isHidden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.icon", + "type": "string", + "tags": [], + "label": "icon", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"query\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.EventAnnotationConfig.key", + "type": "Object", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "{ type: \"point_in_time\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.Filter", @@ -9533,6 +9738,88 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.XYAnnotationsLayerConfig", + "type": "Interface", + "tags": [], + "label": "XYAnnotationsLayerConfig", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.XYAnnotationsLayerConfig.layerId", + "type": "string", + "tags": [], + "label": "layerId", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.XYAnnotationsLayerConfig.annotations", + "type": "Array", + "tags": [], + "label": "annotations", + "description": [], + "signature": [ + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.EventAnnotationConfig", + "text": "EventAnnotationConfig" + }, + "[]" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.XYAnnotationsLayerConfig.ignoreGlobalFilters", + "type": "boolean", + "tags": [], + "label": "ignoreGlobalFilters", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.XYAnnotationsLayerConfig.layerType", + "type": "string", + "tags": [], + "label": "layerType", + "description": [], + "signature": [ + "\"annotations\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.XYAnnotationsLayerConfig.indexPatternId", + "type": "string", + "tags": [], + "label": "indexPatternId", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.XYConfiguration", @@ -11742,6 +12029,14 @@ "docId": "kibVisualizationsPluginApi", "section": "def-common.XYReferenceLineLayerConfig", "text": "XYReferenceLineLayerConfig" + }, + " | ", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.XYAnnotationsLayerConfig", + "text": "XYAnnotationsLayerConfig" } ], "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 86e1618717ea1..90b1267c266a9 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: 2022-09-20 +date: 2022-09-21 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 611 | 12 | 582 | 14 | +| 630 | 12 | 601 | 14 | ## Client diff --git a/docs/developer/contributing/development-functional-tests.asciidoc b/docs/developer/contributing/development-functional-tests.asciidoc index 2d47ad92582bb..cf854c6d53cfa 100644 --- a/docs/developer/contributing/development-functional-tests.asciidoc +++ b/docs/developer/contributing/development-functional-tests.asciidoc @@ -31,18 +31,23 @@ There are three ways to run the tests depending on your goals: 3. Custom option: ** Description: Runs tests against instances of {es} & {kib} started some other way (like Elastic Cloud, or an instance you are managing in some other way). -** just executes the functional tests -** url, credentials, etc. for {es} and {kib} are specified via environment variables -** Here's an example that runs against an Elastic Cloud instance. Note that you must run the same branch of tests as the version of {kib} you're testing. +** Just executes the functional tests +** URL, credentials, etc. for {es} and {kib} are specified via environment variables +** When running against an Elastic Cloud instance, additional environment variables are required `TEST_CLOUD` and `ES_SECURITY_ENABLED` +** You must run the same branch of tests as the version of {kib} you're testing. To run against a previous minor version use option `--es-version ` +** To run a specific configuration use option `--config ` +** Here's an example that runs against an Elastic Cloud instance + ["source","shell"] ---------- -export TEST_KIBANA_URL=https://kibana:password@my-kibana-instance.internal.net:443 +export TEST_KIBANA_URL=https://elastic:password@my-kbn-cluster.elastic-cloud.com:443 +export TEST_ES_URL=https://elastic:password@my-es-cluster.elastic-cloud.com:443 -export TEST_ES_URL=https://elastic:password@my-es-cluster.internal.net:9200 -node scripts/functional_test_runner ----------- +export TEST_CLOUD=1 +export ES_SECURITY_ENABLED=1 +node scripts/functional_test_runner [--config ] [--es-version ] +---------- ** Or you can override any or all of these individual parts of the URL and leave the others to the default values. + @@ -527,4 +532,4 @@ If your functional tests are flaky then the Operations team might skip them and This will take you to Buildkite where your build will run and tell you if it failed in any execution. -A flaky test may only fail once in 1000 runs, so keep this in mind and make sure you use enough executions to really prove that a test isn't flaky anymore. \ No newline at end of file +A flaky test may only fail once in 1000 runs, so keep this in mind and make sure you use enough executions to really prove that a test isn't flaky anymore. diff --git a/docs/settings/apm-settings.asciidoc b/docs/settings/apm-settings.asciidoc index de5e8c686c61b..fba7a32e17f1b 100644 --- a/docs/settings/apm-settings.asciidoc +++ b/docs/settings/apm-settings.asciidoc @@ -77,6 +77,9 @@ Maximum number of child items displayed when viewing trace details. Defaults to `xpack.observability.annotations.index` {ess-icon}:: Index name where Observability annotations are stored. Defaults to `observability-annotations`. +`xpack.apm.searchAggregatedServiceMetrics` {ess-icon}:: + Enables Service metrics. Defaults to `false`. When set to `true`, additional configuration in APM Server is required. + `xpack.apm.searchAggregatedTransactions` {ess-icon}:: Enables Transaction histogram metrics. Defaults to `auto` so the UI will use metric indices over transaction indices for transactions if aggregated transactions are found. When set to `always`, additional configuration in APM Server is required. When set to `never` and aggregated transactions are not used. + diff --git a/package.json b/package.json index d895c8d00e819..c138d74d8f0a8 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "@dnd-kit/utilities": "^2.0.0", "@elastic/apm-rum": "^5.12.0", "@elastic/apm-rum-react": "^1.4.2", - "@elastic/charts": "48.0.1", + "@elastic/charts": "49.0.0", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.3.0-canary.1", "@elastic/ems-client": "8.3.3", @@ -416,6 +416,7 @@ "@turf/distance": "6.0.1", "@turf/helpers": "6.0.1", "@turf/length": "^6.0.2", + "@types/byte-size": "^8.1.0", "JSONStream": "1.3.5", "abort-controller": "^3.0.0", "antlr4ts": "^0.5.0-alpha.3", @@ -424,6 +425,7 @@ "base64-js": "^1.3.1", "bitmap-sdf": "^1.0.3", "brace": "0.11.1", + "byte-size": "^8.1.0", "canvg": "^3.0.9", "cbor-x": "^1.3.3", "chalk": "^4.1.0", @@ -635,7 +637,6 @@ "whatwg-fetch": "^3.0.0", "xml2js": "^0.4.22", "xterm": "^4.18.0", - "xterm-addon-fit": "^0.5.0", "yauzl": "^2.10.0", "yazl": "^2.5.1" }, diff --git a/packages/core/saved-objects/core-saved-objects-api-browser/index.ts b/packages/core/saved-objects/core-saved-objects-api-browser/index.ts index 9fc3e6a78c5c0..e78c56d76556c 100644 --- a/packages/core/saved-objects/core-saved-objects-api-browser/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-browser/index.ts @@ -22,4 +22,7 @@ export type { SavedObjectsBulkUpdateOptions, SavedObjectsBulkResolveResponse, SavedObjectsBulkCreateObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponseItem, + SavedObjectsBulkDeleteResponse, } from './src/apis'; diff --git a/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts b/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts new file mode 100644 index 0000000000000..1e4b5d2268dea --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/bulk_delete.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SavedObjectError } from '@kbn/core-saved-objects-common'; + +/** @public */ +export interface SavedObjectsBulkDeleteOptions { + force?: boolean; +} + +/** @public */ +export interface SavedObjectsBulkDeleteResponseItem { + id: string; + type: string; + success: boolean; + error?: SavedObjectError; +} + +/** @public */ +export interface SavedObjectsBulkDeleteResponse { + statuses: SavedObjectsBulkDeleteResponseItem[]; +} diff --git a/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/index.ts b/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/index.ts index 4652facb972cc..afee0a01494e1 100644 --- a/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-browser/src/apis/index.ts @@ -19,3 +19,8 @@ export type { } from './find'; export type { ResolvedSimpleSavedObject } from './resolve'; export type { SavedObjectsUpdateOptions } from './update'; +export type { + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponseItem, + SavedObjectsBulkDeleteResponse, +} from './bulk_delete'; diff --git a/packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts index 123b5c81d4064..d222770a8579d 100644 --- a/packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-api-browser/src/saved_objects_client.ts @@ -19,7 +19,10 @@ import type { SavedObjectsFindOptions, SavedObjectsUpdateOptions, SavedObjectsDeleteOptions, + SavedObjectsBulkDeleteResponse, + SavedObjectsBulkDeleteOptions, } from './apis'; + import type { SimpleSavedObject } from './simple_saved_object'; /** @@ -52,6 +55,17 @@ export interface SavedObjectsClientContract { */ delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; + /** + * Deletes multiple documents at once + * @param objects - an array of objects containing id, type + * @param options - optional force argument to force deletion of objects in a namespace other than the scoped client + * @returns The bulk delete result for the saved objects for the given types and ids. + */ + bulkDelete( + objects: SavedObjectTypeIdTuple[], + options?: SavedObjectsBulkDeleteOptions + ): Promise; + /** * Search for objects * diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts index c86945c6acb5c..0739c9acab8f5 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts @@ -46,6 +46,8 @@ import type { SavedObjectsCollectMultiNamespaceReferencesResponse, SavedObjectsUpdateObjectsSpacesObject, SavedObjectsUpdateObjectsSpacesOptions, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, } from '@kbn/core-saved-objects-api-server'; import type { SavedObjectsType, @@ -2044,6 +2046,517 @@ describe('SavedObjectsRepository', () => { }); }); + describe('#bulkDelete', () => { + const obj1: SavedObjectsBulkDeleteObject = { + type: 'config', + id: '6.0.0-alpha1', + }; + const obj2: SavedObjectsBulkDeleteObject = { + type: 'index-pattern', + id: 'logstash-*', + }; + + const namespace = 'foo-namespace'; + + const createNamespaceAwareGetId = (type: string, id: string) => + `${registry.isSingleNamespace(type) && namespace ? `${namespace}:` : ''}${type}:${id}`; + + const getMockEsBulkDeleteResponse = ( + objects: TypeIdTuple[], + options?: SavedObjectsBulkDeleteOptions + ) => + ({ + items: objects.map(({ type, id }) => ({ + // es response returns more fields than what we're interested in. + delete: { + _id: `${ + registry.isSingleNamespace(type) && options?.namespace ? `${options?.namespace}:` : '' + }${type}:${id}`, + ...mockVersionProps, + result: 'deleted', + }, + })), + } as estypes.BulkResponse); + + const repositoryBulkDeleteSuccess = async ( + objects: SavedObjectsBulkDeleteObject[] = [], + options?: SavedObjectsBulkDeleteOptions, + internalOptions: { + mockMGetResponseWithObject?: { initialNamespaces: string[]; type: string; id: string }; + } = {} + ) => { + const multiNamespaceObjects = objects.filter(({ type }) => { + return registry.isMultiNamespace(type); + }); + + const { mockMGetResponseWithObject } = internalOptions; + if (multiNamespaceObjects.length > 0) { + const mockedMGetResponse = mockMGetResponseWithObject + ? getMockMgetResponse([mockMGetResponseWithObject], options?.namespace) + : getMockMgetResponse(multiNamespaceObjects, options?.namespace); + client.mget.mockResponseOnce(mockedMGetResponse); + } + const mockedEsBulkDeleteResponse = getMockEsBulkDeleteResponse(objects, options); + + client.bulk.mockResponseOnce(mockedEsBulkDeleteResponse); + const result = await savedObjectsRepository.bulkDelete(objects, options); + + expect(client.mget).toHaveBeenCalledTimes(multiNamespaceObjects?.length ? 1 : 0); + return result; + }; + + // bulk delete calls only has one object for each source -- the action + const expectClientCallBulkDeleteArgsAction = ( + objects: TypeIdTuple[], + { + method, + _index = expect.any(String), + getId = () => expect.any(String), + overrides = {}, + }: { + method: string; + _index?: string; + getId?: (type: string, id: string) => string; + overrides?: Record; + } + ) => { + const body = []; + for (const { type, id } of objects) { + body.push({ + [method]: { + _index, + _id: getId(type, id), + ...overrides, + }, + }); + } + + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + }; + + const createBulkDeleteFailStatus = ({ + type, + id, + error, + }: { + type: string; + id: string; + error?: ExpectedErrorResult['error']; + }) => ({ + type, + id, + success: false, + error: error ?? createBadRequestError(), + }); + + const createBulkDeleteSuccessStatus = ({ type, id }: { type: string; id: string }) => ({ + type, + id, + success: true, + }); + + // mocks a combination of success, error results for hidden and unknown object object types. + const repositoryBulkDeleteError = async ( + obj: SavedObjectsBulkDeleteObject, + isBulkError: boolean, + expectedErrorResult: ExpectedErrorResult + ) => { + const objects = [obj1, obj, obj2]; + const mockedBulkDeleteResponse = getMockEsBulkDeleteResponse(objects); + if (isBulkError) { + mockGetBulkOperationError.mockReturnValueOnce(undefined); + mockGetBulkOperationError.mockReturnValueOnce(expectedErrorResult.error as Payload); + } + client.bulk.mockResponseOnce(mockedBulkDeleteResponse); + + const result = await savedObjectsRepository.bulkDelete(objects); + expect(client.bulk).toHaveBeenCalled(); + expect(result).toEqual({ + statuses: [ + createBulkDeleteSuccessStatus(obj1), + createBulkDeleteFailStatus({ ...obj, error: expectedErrorResult.error }), + createBulkDeleteSuccessStatus(obj2), + ], + }); + }; + + const expectClientCallArgsAction = ( + objects: TypeIdTuple[], + { + method, + _index = expect.any(String), + getId = () => expect.any(String), + overrides = {}, + }: { + method: string; + _index?: string; + getId?: (type: string, id: string) => string; + overrides?: Record; + } + ) => { + const body = []; + for (const { type, id } of objects) { + body.push({ + [method]: { + _index, + _id: getId(type, id), + ...overrides, + }, + }); + } + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + }; + + const bulkDeleteMultiNamespaceError = async ( + [obj1, _obj, obj2]: SavedObjectsBulkDeleteObject[], + options: SavedObjectsBulkDeleteOptions | undefined, + mgetResponse: estypes.MgetResponse, + mgetOptions?: { statusCode?: number } + ) => { + const getId = (type: string, id: string) => `${options?.namespace}:${type}:${id}`; + // mock the response for the not found doc + client.mget.mockResponseOnce(mgetResponse, { statusCode: mgetOptions?.statusCode }); + // get a mocked response for the valid docs + const bulkResponse = getMockEsBulkDeleteResponse([obj1, obj2], { namespace }); + client.bulk.mockResponseOnce(bulkResponse); + + const result = await savedObjectsRepository.bulkDelete([obj1, _obj, obj2], options); + expect(client.bulk).toHaveBeenCalledTimes(1); + expect(client.mget).toHaveBeenCalledTimes(1); + + expectClientCallArgsAction([obj1, obj2], { method: 'delete', getId }); + expect(result).toEqual({ + statuses: [ + createBulkDeleteSuccessStatus(obj1), + { ...expectErrorNotFound(_obj), success: false }, + createBulkDeleteSuccessStatus(obj2), + ], + }); + }; + + beforeEach(() => { + mockDeleteLegacyUrlAliases.mockClear(); + mockDeleteLegacyUrlAliases.mockResolvedValue(); + }); + + describe('client calls', () => { + it(`should use the ES bulk action by default`, async () => { + await repositoryBulkDeleteSuccess([obj1, obj2]); + expect(client.bulk).toHaveBeenCalled(); + }); + + it(`should use the ES mget action before bulk action for any types that are multi-namespace`, async () => { + const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }]; + await repositoryBulkDeleteSuccess(objects); + expect(client.bulk).toHaveBeenCalled(); + expect(client.mget).toHaveBeenCalled(); + + const docs = [ + expect.objectContaining({ _id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${obj2.id}` }), + ]; + expect(client.mget).toHaveBeenCalledWith( + expect.objectContaining({ body: { docs } }), + expect.anything() + ); + }); + + it(`should not use the ES bulk action when there are no valid documents to delete`, async () => { + const objects = [obj1, obj2].map((x) => ({ ...x, type: 'unknownType' })); + await savedObjectsRepository.bulkDelete(objects); + expect(client.bulk).toHaveBeenCalledTimes(0); + }); + + it(`formats the ES request`, async () => { + const getId = createNamespaceAwareGetId; + await repositoryBulkDeleteSuccess([obj1, obj2], { namespace }); + expectClientCallBulkDeleteArgsAction([obj1, obj2], { method: 'delete', getId }); + }); + + it(`formats the ES request for any types that are multi-namespace`, async () => { + const _obj2 = { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }; + const getId = createNamespaceAwareGetId; + await repositoryBulkDeleteSuccess([obj1, _obj2], { namespace }); + expectClientCallBulkDeleteArgsAction([obj1, _obj2], { method: 'delete', getId }); + }); + + it(`defaults to a refresh setting of wait_for`, async () => { + await repositoryBulkDeleteSuccess([obj1, obj2]); + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ refresh: 'wait_for' }), + expect.anything() + ); + }); + + it(`does not include the version of the existing document when not using a multi-namespace type`, async () => { + const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; + await repositoryBulkDeleteSuccess(objects); + expectClientCallBulkDeleteArgsAction(objects, { method: 'delete' }); + }); + + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + const getId = createNamespaceAwareGetId; + await repositoryBulkDeleteSuccess([obj1, obj2], { namespace }); + expectClientCallBulkDeleteArgsAction([obj1, obj2], { method: 'delete', getId }); + }); + + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + const getId = (type: string, id: string) => `${type}:${id}`; + await repositoryBulkDeleteSuccess([obj1, obj2]); + expectClientCallBulkDeleteArgsAction([obj1, obj2], { method: 'delete', getId }); + }); + + it(`normalizes options.namespace from 'default' to undefined`, async () => { + const getId = (type: string, id: string) => `${type}:${id}`; + await repositoryBulkDeleteSuccess([obj1, obj2], { namespace: 'default' }); + expectClientCallBulkDeleteArgsAction([obj1, obj2], { method: 'delete', getId }); + }); + + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + const getId = (type: string, id: string) => `${type}:${id}`; // not expecting namespace prefix; + const _obj1 = { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }; + const _obj2 = { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }; + + await repositoryBulkDeleteSuccess([_obj1, _obj2], { namespace }); + expectClientCallBulkDeleteArgsAction([_obj1, _obj2], { method: 'delete', getId }); + }); + }); + + describe('legacy URL aliases', () => { + it(`doesn't delete legacy URL aliases for single-namespace object types`, async () => { + await repositoryBulkDeleteSuccess([obj1, obj2]); + expect(mockDeleteLegacyUrlAliases).not.toHaveBeenCalled(); + }); + + it(`deletes legacy URL aliases for multi-namespace object types (all spaces)`, async () => { + const testObject = { ...obj1, type: MULTI_NAMESPACE_TYPE }; + const internalOptions = { + mockMGetResponseWithObject: { + ...testObject, + initialNamespaces: [ALL_NAMESPACES_STRING], + }, + }; + await repositoryBulkDeleteSuccess( + [testObject], + { namespace, force: true }, + internalOptions + ); + expect(mockDeleteLegacyUrlAliases).toHaveBeenCalledWith( + expect.objectContaining({ + type: MULTI_NAMESPACE_TYPE, + id: testObject.id, + namespaces: [], + deleteBehavior: 'exclusive', + }) + ); + }); + + it(`deletes legacy URL aliases for multi-namespace object types (specific space)`, async () => { + const testObject = { ...obj1, type: MULTI_NAMESPACE_TYPE }; + const internalOptions = { + mockMGetResponseWithObject: { + ...testObject, + initialNamespaces: [namespace], + }, + }; + // specifically test against the current namespace + await repositoryBulkDeleteSuccess([testObject], { namespace }, internalOptions); + expect(mockDeleteLegacyUrlAliases).toHaveBeenCalledWith( + expect.objectContaining({ + type: MULTI_NAMESPACE_TYPE, + id: testObject.id, + namespaces: [namespace], + deleteBehavior: 'inclusive', + }) + ); + }); + + it(`deletes legacy URL aliases for multi-namespace object types shared to many specific spaces`, async () => { + const testObject = { ...obj1, type: MULTI_NAMESPACE_TYPE }; + const initialTestObjectNamespaces = [namespace, 'bar-namespace']; + const internalOptions = { + mockMGetResponseWithObject: { + ...testObject, + initialNamespaces: initialTestObjectNamespaces, + }, + }; + // specifically test against named spaces ('*' is handled specifically, this assures we also take care of named spaces) + await repositoryBulkDeleteSuccess( + [testObject], + { namespace, force: true }, + internalOptions + ); + expect(mockDeleteLegacyUrlAliases).toHaveBeenCalledWith( + expect.objectContaining({ + type: MULTI_NAMESPACE_TYPE, + id: testObject.id, + namespaces: initialTestObjectNamespaces, + deleteBehavior: 'inclusive', + }) + ); + }); + + it(`logs a message when deleteLegacyUrlAliases returns an error`, async () => { + const testObject = { type: MULTI_NAMESPACE_ISOLATED_TYPE, id: obj1.id }; + + client.mget.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise( + getMockMgetResponse([testObject], namespace) + ) + ); + const mockedBulkResponse = getMockEsBulkDeleteResponse([testObject], { namespace }); + client.bulk.mockResolvedValueOnce(mockedBulkResponse); + + mockDeleteLegacyUrlAliases.mockRejectedValueOnce(new Error('Oh no!')); + + await savedObjectsRepository.bulkDelete([testObject], { namespace }); + + expect(client.mget).toHaveBeenCalledTimes(1); + expect(logger.error).toHaveBeenCalledTimes(1); + expect(logger.error).toHaveBeenCalledWith( + 'Unable to delete aliases when deleting an object: Oh no!' + ); + }); + }); + + describe('errors', () => { + it(`throws an error when options.namespace is '*'`, async () => { + await expect( + savedObjectsRepository.bulkDelete([obj1], { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); + }); + + it(`throws an error when client bulk response is not defined`, async () => { + client.mget.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise( + getMockMgetResponse([obj1], namespace) + ) + ); + const mockedBulkResponse = undefined; + // we have to cast here to test the assumption we always get a response. + client.bulk.mockResponseOnce(mockedBulkResponse as unknown as estypes.BulkResponse); + await expect(savedObjectsRepository.bulkDelete([obj1], { namespace })).rejects.toThrowError( + 'Unexpected error in bulkDelete saved objects: bulkDeleteResponse is undefined' + ); + }); + + it(`returns an error for the object when the object's type is invalid`, async () => { + const unknownObjType = { ...obj1, type: 'unknownType' }; + await repositoryBulkDeleteError( + unknownObjType, + false, + expectErrorInvalidType(unknownObjType) + ); + }); + + it(`returns an error for an object when the object's type is hidden`, async () => { + const hiddenObject = { ...obj1, type: HIDDEN_TYPE }; + await repositoryBulkDeleteError(hiddenObject, false, expectErrorInvalidType(hiddenObject)); + }); + + it(`returns an error when ES is unable to find the document during mget`, async () => { + const notFoundObj = { ...obj1, type: MULTI_NAMESPACE_ISOLATED_TYPE, found: false }; + const mgetResponse = getMockMgetResponse([notFoundObj], namespace); + await bulkDeleteMultiNamespaceError([obj1, notFoundObj, obj2], { namespace }, mgetResponse); + }); + + it(`returns an error when ES is unable to find the index during mget`, async () => { + const notFoundObj = { ...obj1, type: MULTI_NAMESPACE_ISOLATED_TYPE, found: false }; + await bulkDeleteMultiNamespaceError( + [obj1, notFoundObj, obj2], + { namespace }, + {} as estypes.MgetResponse, + { + statusCode: 404, + } + ); + }); + + it(`returns an error when the type is multi-namespace and the document exists, but not in this namespace`, async () => { + const obj = { + type: MULTI_NAMESPACE_ISOLATED_TYPE, + id: 'three', + namespace: 'bar-namespace', + }; + const mgetResponse = getMockMgetResponse([obj], namespace); + await bulkDeleteMultiNamespaceError([obj1, obj, obj2], { namespace }, mgetResponse); + }); + + it(`returns an error when the type is multi-namespace and the document has multiple namespaces and the force option is not enabled`, async () => { + const testObject = { ...obj1, type: MULTI_NAMESPACE_TYPE }; + const internalOptions = { + mockMGetResponseWithObject: { + ...testObject, + initialNamespaces: [namespace, 'bar-namespace'], + }, + }; + const result = await repositoryBulkDeleteSuccess( + [testObject], + { namespace }, + internalOptions + ); + expect(result.statuses[0]).toStrictEqual( + createBulkDeleteFailStatus({ + ...testObject, + error: createBadRequestError( + 'Unable to delete saved object that exists in multiple namespaces, use the "force" option to delete it anyway' + ), + }) + ); + }); + + it(`returns an error when the type is multi-namespace and the document has all namespaces and the force option is not enabled`, async () => { + const testObject = { ...obj1, type: ALL_NAMESPACES_STRING }; + const internalOptions = { + mockMGetResponseWithObject: { + ...testObject, + initialNamespaces: [namespace, 'bar-namespace'], + }, + }; + const result = await repositoryBulkDeleteSuccess( + [testObject], + { namespace }, + internalOptions + ); + expect(result.statuses[0]).toStrictEqual( + createBulkDeleteFailStatus({ + ...testObject, + error: createBadRequestError("Unsupported saved object type: '*'"), + }) + ); + }); + }); + + describe('returns', () => { + it(`returns early for empty objects argument`, async () => { + await savedObjectsRepository.bulkDelete([], { namespace }); + expect(client.bulk).toHaveBeenCalledTimes(0); + }); + + it(`formats the ES response`, async () => { + const response = await repositoryBulkDeleteSuccess([obj1, obj2], { namespace }); + expect(response).toEqual({ + statuses: [obj1, obj2].map(createBulkDeleteSuccessStatus), + }); + }); + + it(`handles a mix of successful deletes and errors`, async () => { + const notFoundObj = { ...obj1, type: MULTI_NAMESPACE_ISOLATED_TYPE, found: false }; + await bulkDeleteMultiNamespaceError( + [obj1, notFoundObj, obj2], + { namespace }, + {} as estypes.MgetResponse, + { statusCode: 404 } + ); + }); + }); + }); + describe('#checkConflicts', () => { const obj1 = { type: 'dashboard', id: 'one' }; const obj2 = { type: 'dashboard', id: 'two' }; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts index 961b44a1cd688..5569141c7fa0e 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.ts @@ -54,6 +54,9 @@ import type { SavedObjectsClosePointInTimeOptions, SavedObjectsCreatePointInTimeFinderOptions, SavedObjectsFindOptions, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponse, } from '@kbn/core-saved-objects-api-server'; import type { SavedObjectSanitizedDoc, @@ -83,6 +86,7 @@ import { type IndexMapping, type IKibanaMigrator, } from '@kbn/core-saved-objects-base-server-internal'; +import pMap from 'p-map'; import { PointInTimeFinder } from './point_in_time_finder'; import { createRepositoryEsClient, RepositoryEsClient } from './repository_es_client'; import { getSearchDsl } from './search_dsl'; @@ -109,6 +113,16 @@ import { PreflightCheckForCreateObject, } from './preflight_check_for_create'; import { deleteLegacyUrlAliases } from './legacy_url_aliases'; +import type { + BulkDeleteParams, + ExpectedBulkDeleteResult, + BulkDeleteItemErrorResult, + NewBulkItemResponse, + BulkDeleteExpectedBulkGetResult, + PreflightCheckForBulkDeleteParams, + ExpectedBulkDeleteMultiNamespaceDocsParams, + ObjectToDeleteAliasesFor, +} from './repository_bulk_delete_internal_types'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. @@ -127,6 +141,7 @@ export interface SavedObjectsRepositoryOptions { export const DEFAULT_REFRESH_SETTING = 'wait_for'; export const DEFAULT_RETRY_COUNT = 3; +const MAX_CONCURRENT_ALIAS_DELETIONS = 10; /** * @internal */ @@ -676,7 +691,6 @@ export class SavedObjectsRepository implements ISavedObjectsRepository { if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - const { refresh = DEFAULT_REFRESH_SETTING, force } = options; const namespace = normalizeNamespace(options.namespace); @@ -762,6 +776,286 @@ export class SavedObjectsRepository implements ISavedObjectsRepository { ); } + /** + * Performs initial checks on object type validity and flags multi-namespace objects for preflight checks by adding an `esRequestIndex` + * @param objects SavedObjectsBulkDeleteObject[] + * @returns array BulkDeleteExpectedBulkGetResult[] + * @internal + */ + private presortObjectsByNamespaceType(objects: SavedObjectsBulkDeleteObject[]) { + let bulkGetRequestIndexCounter = 0; + return objects.map((object) => { + const { type, id } = object; + if (!this._allowedTypes.includes(type)) { + return { + tag: 'Left', + value: { + id, + type, + error: errorContent(SavedObjectsErrorHelpers.createUnsupportedTypeError(type)), + }, + }; + } + const requiresNamespacesCheck = this._registry.isMultiNamespace(type); + return { + tag: 'Right', + value: { + type, + id, + ...(requiresNamespacesCheck && { esRequestIndex: bulkGetRequestIndexCounter++ }), + }, + }; + }); + } + + /** + * Fetch multi-namespace saved objects + * @returns MgetResponse + * @notes multi-namespace objects shared to more than one space require special handling. We fetch these docs to retrieve their namespaces. + * @internal + */ + private async preflightCheckForBulkDelete(params: PreflightCheckForBulkDeleteParams) { + const { expectedBulkGetResults, namespace } = params; + const bulkGetMultiNamespaceDocs = expectedBulkGetResults + .filter(isRight) + .filter(({ value }) => value.esRequestIndex !== undefined) + .map(({ value: { type, id } }) => ({ + _id: this._serializer.generateRawId(namespace, type, id), + _index: this.getIndexForType(type), + _source: ['type', 'namespaces'], + })); + + const bulkGetMultiNamespaceDocsResponse = bulkGetMultiNamespaceDocs.length + ? await this.client.mget( + { body: { docs: bulkGetMultiNamespaceDocs } }, + { ignore: [404], meta: true } + ) + : undefined; + // fail fast if we can't verify a 404 response is from Elasticsearch + if ( + bulkGetMultiNamespaceDocsResponse && + isNotFoundFromUnsupportedServer({ + statusCode: bulkGetMultiNamespaceDocsResponse.statusCode, + headers: bulkGetMultiNamespaceDocsResponse.headers, + }) + ) { + throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); + } + return bulkGetMultiNamespaceDocsResponse; + } + + /** + * @returns array of objects sorted by expected delete success or failure result + * @internal + */ + private getExpectedBulkDeleteMultiNamespaceDocsResults( + params: ExpectedBulkDeleteMultiNamespaceDocsParams + ): ExpectedBulkDeleteResult[] { + const { expectedBulkGetResults, multiNamespaceDocsResponse, namespace, force } = params; + let indexCounter = 0; + const expectedBulkDeleteMultiNamespaceDocsResults = + expectedBulkGetResults.map((expectedBulkGetResult) => { + if (isLeft(expectedBulkGetResult)) { + return { ...expectedBulkGetResult }; + } + const { esRequestIndex: esBulkGetRequestIndex, id, type } = expectedBulkGetResult.value; + + let namespaces; + + if (esBulkGetRequestIndex !== undefined) { + const indexFound = multiNamespaceDocsResponse?.statusCode !== 404; + + const actualResult = indexFound + ? multiNamespaceDocsResponse?.body.docs[esBulkGetRequestIndex] + : undefined; + + const docFound = indexFound && isMgetDoc(actualResult) && actualResult.found; + + // return an error if the doc isn't found at all or the doc doesn't exist in the namespaces + if (!docFound) { + return { + tag: 'Left', + value: { + id, + type, + error: errorContent(SavedObjectsErrorHelpers.createGenericNotFoundError(type, id)), + }, + }; + } + // the following check should be redundant since we're retrieving the docs from elasticsearch but we check just to make sure + // @ts-expect-error MultiGetHit is incorrectly missing _id, _source + if (!this.rawDocExistsInNamespace(actualResult, namespace)) { + return { + tag: 'Left', + value: { + id, + type, + error: errorContent(SavedObjectsErrorHelpers.createGenericNotFoundError(type, id)), + }, + }; + } + // @ts-expect-error MultiGetHit is incorrectly missing _id, _source + namespaces = actualResult!._source.namespaces ?? [ + SavedObjectsUtils.namespaceIdToString(namespace), + ]; + const useForce = force && force === true ? true : false; + // the document is shared to more than one space and can only be deleted by force. + if (!useForce && (namespaces.length > 1 || namespaces.includes(ALL_NAMESPACES_STRING))) { + return { + tag: 'Left', + value: { + success: false, + id, + type, + error: errorContent( + SavedObjectsErrorHelpers.createBadRequestError( + `Unable to delete saved object that exists in multiple namespaces, use the "force" option to delete it anyway` + ) + ), + }, + }; + } + } + // contains all objects that passed initial preflight checks, including single namespace objects that skipped the mget call + // single namespace objects will have namespaces:undefined + const expectedResult = { + type, + id, + namespaces, + esRequestIndex: indexCounter++, + }; + + return { tag: 'Right', value: expectedResult }; + }); + return expectedBulkDeleteMultiNamespaceDocsResults; + } + + /** + * {@inheritDoc ISavedObjectsRepository.bulkDelete} + */ + async bulkDelete( + objects: SavedObjectsBulkDeleteObject[], + options: SavedObjectsBulkDeleteOptions = {} + ): Promise { + const { refresh = DEFAULT_REFRESH_SETTING, force } = options; + const namespace = normalizeNamespace(options.namespace); + const expectedBulkGetResults = this.presortObjectsByNamespaceType(objects); + const multiNamespaceDocsResponse = await this.preflightCheckForBulkDelete({ + expectedBulkGetResults, + namespace, + }); + const bulkDeleteParams: BulkDeleteParams[] = []; + + const expectedBulkDeleteMultiNamespaceDocsResults = + this.getExpectedBulkDeleteMultiNamespaceDocsResults({ + expectedBulkGetResults, + multiNamespaceDocsResponse, + namespace, + force, + }); + // bulk up the bulkDeleteParams + expectedBulkDeleteMultiNamespaceDocsResults.map((expectedResult) => { + if (isRight(expectedResult)) { + bulkDeleteParams.push({ + delete: { + _id: this._serializer.generateRawId( + namespace, + expectedResult.value.type, + expectedResult.value.id + ), + _index: this.getIndexForType(expectedResult.value.type), + ...getExpectedVersionProperties(undefined), + }, + }); + } + }); + + const bulkDeleteResponse = bulkDeleteParams.length + ? await this.client.bulk({ + refresh, + body: bulkDeleteParams, + require_alias: true, + }) + : undefined; + + // extracted to ensure consistency in the error results returned + let errorResult: BulkDeleteItemErrorResult; + const objectsToDeleteAliasesFor: ObjectToDeleteAliasesFor[] = []; + + const savedObjects = expectedBulkDeleteMultiNamespaceDocsResults.map((expectedResult) => { + if (isLeft(expectedResult)) { + return { ...expectedResult.value, success: false }; + } + const { + type, + id, + namespaces, + esRequestIndex: esBulkDeleteRequestIndex, + } = expectedResult.value; + // we assume this wouldn't happen but is needed to ensure type consistency + if (bulkDeleteResponse === undefined) { + throw new Error( + `Unexpected error in bulkDelete saved objects: bulkDeleteResponse is undefined` + ); + } + const rawResponse = Object.values( + bulkDeleteResponse.items[esBulkDeleteRequestIndex] + )[0] as NewBulkItemResponse; + + const error = getBulkOperationError(type, id, rawResponse); + if (error) { + errorResult = { success: false, type, id, error }; + return errorResult; + } + if (rawResponse.result === 'not_found') { + errorResult = { + success: false, + type, + id, + error: errorContent(SavedObjectsErrorHelpers.createGenericNotFoundError(type, id)), + }; + return errorResult; + } + + if (rawResponse.result === 'deleted') { + // `namespaces` should only exist in the expectedResult.value if the type is multi-namespace. + if (namespaces) { + objectsToDeleteAliasesFor.push({ + type, + id, + ...(namespaces.includes(ALL_NAMESPACES_STRING) + ? { namespaces: [], deleteBehavior: 'exclusive' } + : { namespaces, deleteBehavior: 'inclusive' }), + }); + } + } + const successfulResult = { + success: true, + id, + type, + }; + return successfulResult; + }); + + // Delete aliases if necessary, ensuring we don't have too many concurrent operations running. + const mapper = async ({ type, id, namespaces, deleteBehavior }: ObjectToDeleteAliasesFor) => + await deleteLegacyUrlAliases({ + mappings: this._mappings, + registry: this._registry, + client: this.client, + getIndexForType: this.getIndexForType.bind(this), + type, + id, + namespaces, + deleteBehavior, + }).catch((err) => { + this._logger.error(`Unable to delete aliases when deleting an object: ${err.message}`); + }); + await pMap(objectsToDeleteAliasesFor, mapper, { concurrency: MAX_CONCURRENT_ALIAS_DELETIONS }); + + return { statuses: [...savedObjects] }; + } + /** * {@inheritDoc ISavedObjectsRepository.deleteByNamespace} */ diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository_bulk_delete_internal_types.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository_bulk_delete_internal_types.ts new file mode 100644 index 0000000000000..93d4354d8d7e8 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository_bulk_delete_internal_types.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { Payload } from '@hapi/boom'; +import { + BulkOperationBase, + BulkResponseItem, + ErrorCause, +} from '@elastic/elasticsearch/lib/api/types'; +import type { estypes, TransportResult } from '@elastic/elasticsearch'; +import { Either } from './internal_utils'; +import { DeleteLegacyUrlAliasesParams } from './legacy_url_aliases'; + +/** + * @internal + */ +export interface PreflightCheckForBulkDeleteParams { + expectedBulkGetResults: BulkDeleteExpectedBulkGetResult[]; + namespace?: string; +} + +/** + * @internal + */ +export interface ExpectedBulkDeleteMultiNamespaceDocsParams { + // contains the type and id of all objects to delete + expectedBulkGetResults: BulkDeleteExpectedBulkGetResult[]; + // subset of multi-namespace only expectedBulkGetResults + multiNamespaceDocsResponse: TransportResult, unknown> | undefined; + // current namespace in which the bulkDelete call is made + namespace: string | undefined; + // optional parameter used to force delete multinamespace objects that exist in more than the current space + force?: boolean; +} +/** + * @internal + */ +export interface BulkDeleteParams { + delete: Omit; +} + +/** + * @internal + */ +export type ExpectedBulkDeleteResult = Either< + { type: string; id: string; error: Payload }, + { + type: string; + id: string; + namespaces: string[]; + esRequestIndex: number; + } +>; + +/** + * @internal + */ +export interface BulkDeleteItemErrorResult { + success: boolean; + type: string; + id: string; + error: Payload; +} + +/** + * @internal + */ +export type NewBulkItemResponse = BulkResponseItem & { error: ErrorCause & { index: string } }; + +/** + * @internal + * @note Contains all documents for bulk delete, regardless of namespace type + */ +export type BulkDeleteExpectedBulkGetResult = Either< + { type: string; id: string; error: Payload }, + { type: string; id: string; version?: string; esRequestIndex?: number } +>; + +export type ObjectToDeleteAliasesFor = Pick< + DeleteLegacyUrlAliasesParams, + 'type' | 'id' | 'namespaces' | 'deleteBehavior' +>; diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/repository.mock.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/repository.mock.ts index 2cdfcf1710ad4..dc6c06c0c828d 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/repository.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/mocks/repository.mock.ts @@ -16,6 +16,7 @@ const createRepositoryMock = () => { create: jest.fn(), bulkCreate: jest.fn(), bulkUpdate: jest.fn(), + bulkDelete: jest.fn(), delete: jest.fn(), bulkGet: jest.fn(), find: jest.fn(), diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.test.ts index 5829f34a6ba79..38d4e75a0c528 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.test.ts @@ -23,6 +23,8 @@ import type { SavedObjectsFindOptions, SavedObjectsUpdateObjectsSpacesObject, SavedObjectsUpdateObjectsSpacesOptions, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteObject, } from '@kbn/core-saved-objects-api-server'; import { SavedObjectsClient } from './saved_objects_client'; import { repositoryMock, savedObjectsPointInTimeFinderMock } from './mocks'; @@ -119,6 +121,22 @@ describe('SavedObjectsClient', () => { }); }); + test(`#bulkDelete`, async () => { + const returnValue: any = Symbol(); + mockRepository.bulkDelete.mockResolvedValueOnce(returnValue); + const client = new SavedObjectsClient(mockRepository); + + const objects: SavedObjectsBulkDeleteObject[] = [ + { type: 'foo', id: '1' }, + { type: 'bar', id: '2' }, + ]; + const options: SavedObjectsBulkDeleteOptions = { namespace: 'ns-1', refresh: true }; + const result = await client.bulkDelete(objects, options); + + expect(mockRepository.bulkDelete).toHaveBeenCalledWith(objects, options); + expect(result).toBe(returnValue); + }); + test(`#delete`, async () => { const returnValue: any = Symbol(); mockRepository.delete.mockResolvedValueOnce(returnValue); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts index 7c2b3a205b76d..50f78f09dd684 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/saved_objects_client.ts @@ -39,6 +39,9 @@ import type { SavedObjectsClosePointInTimeOptions, SavedObjectsCreatePointInTimeFinderOptions, SavedObjectsFindOptions, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponse, } from '@kbn/core-saved-objects-api-server'; import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-utils-server'; @@ -83,6 +86,14 @@ export class SavedObjectsClient implements SavedObjectsClientContract { return await this._repository.delete(type, id, options); } + /** {@inheritDoc SavedObjectsClientContract.bulkDelete} */ + async bulkDelete( + objects: SavedObjectsBulkDeleteObject[], + options: SavedObjectsBulkDeleteOptions = {} + ): Promise { + return await this._repository.bulkDelete(objects, options); + } + /** {@inheritDoc SavedObjectsClientContract.find} */ async find( options: SavedObjectsFindOptions diff --git a/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/repository.mock.ts b/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/repository.mock.ts index d950b041d2432..168f4c8de6b59 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/repository.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/repository.mock.ts @@ -15,6 +15,7 @@ const create = () => { create: jest.fn(), bulkCreate: jest.fn(), bulkUpdate: jest.fn(), + bulkDelete: jest.fn(), delete: jest.fn(), bulkGet: jest.fn(), find: jest.fn(), diff --git a/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/saved_objects_client.mock.ts b/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/saved_objects_client.mock.ts index 75ee540cb7d8a..523e5003e650f 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/saved_objects_client.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-mocks/src/saved_objects_client.mock.ts @@ -18,6 +18,7 @@ const create = () => { checkConflicts: jest.fn(), bulkUpdate: jest.fn(), delete: jest.fn(), + bulkDelete: jest.fn(), bulkGet: jest.fn(), find: jest.fn(), get: jest.fn(), diff --git a/packages/core/saved-objects/core-saved-objects-api-server/index.ts b/packages/core/saved-objects/core-saved-objects-api-server/index.ts index 1c9688a236920..fdaa5685fbde0 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/index.ts @@ -52,4 +52,8 @@ export type { SavedObjectsCreatePointInTimeFinderOptions, SavedObjectsFindOptions, SavedObjectsPointInTimeFinderClient, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteStatus, + SavedObjectsBulkDeleteResponse, } from './src/apis'; diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts new file mode 100644 index 0000000000000..76d490925c580 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_delete.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SavedObjectError } from '@kbn/core-saved-objects-common'; +import type { MutatingOperationRefreshSetting, SavedObjectsBaseOptions } from './base'; + +/** + * + * @public + */ +export interface SavedObjectsBulkDeleteObject { + type: string; + id: string; +} + +/** + * @public + */ +export interface SavedObjectsBulkDeleteOptions extends SavedObjectsBaseOptions { + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; + /** + * Force deletion of all objects that exists in multiple namespaces, applied to all objects. + */ + force?: boolean; +} + +/** + * @public + */ +export interface SavedObjectsBulkDeleteStatus { + id: string; + type: string; + /** The status of deleting the object: true for deleted, false for error */ + success: boolean; + /** Reason the object could not be deleted (success is false) */ + error?: SavedObjectError; +} + +/** + * @public + */ +export interface SavedObjectsBulkDeleteResponse { + statuses: SavedObjectsBulkDeleteStatus[]; +} diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts index 7dc8e7ab09fc6..d311f2316885d 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/index.ts @@ -72,3 +72,9 @@ export type { SavedObjectsUpdateObjectsSpacesOptions, SavedObjectsUpdateObjectsSpacesResponseObject, } from './update_objects_spaces'; +export type { + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteStatus, + SavedObjectsBulkDeleteResponse, +} from './bulk_delete'; diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts index 82808e4024c73..cfe1f4e6a146b 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_client.ts @@ -41,6 +41,9 @@ import type { SavedObjectsRemoveReferencesToResponse, SavedObjectsCollectMultiNamespaceReferencesOptions, SavedObjectsBulkResponse, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponse, } from './apis'; /** @@ -151,6 +154,16 @@ export interface SavedObjectsClientContract { */ delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; + /** + * Deletes multiple SavedObjects batched together as a single request + * + * @param objects + * @param options + */ + bulkDelete( + objects: SavedObjectsBulkDeleteObject[], + options?: SavedObjectsBulkDeleteOptions + ): Promise; /** * Find all SavedObjects matching the search query * diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts index 102afce9dd73d..d7d2ca57ae3a2 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/saved_objects_repository.ts @@ -44,6 +44,9 @@ import type { SavedObjectsDeleteByNamespaceOptions, SavedObjectsIncrementCounterField, SavedObjectsIncrementCounterOptions, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteResponse, } from './apis'; /** @@ -105,6 +108,17 @@ export interface ISavedObjectsRepository { */ delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; + /** + * Deletes multiple documents at once + * @param {array} objects - an array of objects containing id and type + * @param {object} [options={}] + * @returns {promise} - { statuses: [{ id, type, success, error: { message } }] } + */ + bulkDelete( + objects: SavedObjectsBulkDeleteObject[], + options?: SavedObjectsBulkDeleteOptions + ): Promise; + /** * Deletes all objects from the provided namespace. * diff --git a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.test.ts b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.test.ts index 77391343cd033..6c2966ee9775f 100644 --- a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.test.ts +++ b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.test.ts @@ -308,6 +308,45 @@ describe('SavedObjectsClient', () => { }); }); + describe('#bulk_delete', () => { + const bulkDeleteDoc = { + id: 'AVwSwFxtcMV38qjDZoQg', + type: 'config', + }; + beforeEach(() => { + http.fetch.mockResolvedValue({ + statuses: [{ id: bulkDeleteDoc.id, type: bulkDeleteDoc.type, success: true }], + }); + }); + + test('deletes with an array of id, type and success status for deleted docs', async () => { + const response = savedObjectsClient.bulkDelete([bulkDeleteDoc]); + await expect(response).resolves.toHaveProperty('statuses'); + + const result = await response; + expect(result.statuses).toHaveLength(1); + expect(result.statuses[0]).toHaveProperty('success'); + }); + + test('makes HTTP call', async () => { + await savedObjectsClient.bulkDelete([bulkDeleteDoc]); + expect(http.fetch.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "/api/saved_objects/_bulk_delete", + Object { + "body": "[{\\"type\\":\\"config\\",\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\"}]", + "method": "POST", + "query": Object { + "force": false, + }, + }, + ], + ] + `); + }); + }); + describe('#update', () => { const attributes = { foo: 'Foo', bar: 'Bar' }; const options = { version: '1' }; diff --git a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts index 3a16030983fa9..dd2feed58123f 100644 --- a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts @@ -11,9 +11,11 @@ import type { HttpSetup, HttpFetchOptions } from '@kbn/core-http-browser'; import type { SavedObject, SavedObjectTypeIdTuple } from '@kbn/core-saved-objects-common'; import type { SavedObjectsBulkResolveResponse as SavedObjectsBulkResolveResponseServer, + SavedObjectsBulkDeleteResponse as SavedObjectsBulkDeleteResponseServer, SavedObjectsClientContract as SavedObjectsApi, SavedObjectsFindResponse as SavedObjectsFindResponseServer, SavedObjectsResolveResponse, + SavedObjectsBulkDeleteOptions, } from '@kbn/core-saved-objects-api-server'; import type { SavedObjectsClientContract, @@ -28,6 +30,7 @@ import type { SavedObjectsBulkCreateOptions, SavedObjectsBulkCreateObject, SimpleSavedObject, + SavedObjectsBulkDeleteResponse, } from '@kbn/core-saved-objects-api-browser'; import { SimpleSavedObjectImpl } from './simple_saved_object'; @@ -255,6 +258,31 @@ export class SavedObjectsClient implements SavedObjectsClientContract { return this.savedObjectsFetch(this.getPath([type, id]), { method: 'DELETE', query }); }; + public bulkDelete = async ( + objects: SavedObjectTypeIdTuple[], + options?: SavedObjectsBulkDeleteOptions + ): Promise => { + const filteredObjects = objects.map(({ type, id }) => ({ type, id })); + const queryOptions = { force: !!options?.force }; + const response = await this.performBulkDelete(filteredObjects, queryOptions); + return { + statuses: response.statuses, + }; + }; + + private async performBulkDelete( + objects: SavedObjectTypeIdTuple[], + queryOptions: { force: boolean } + ) { + const path = this.getPath(['_bulk_delete']); + const request: Promise = this.savedObjectsFetch(path, { + method: 'POST', + body: JSON.stringify(objects), + query: queryOptions, + }); + return request; + } + public find = ( options: SavedObjectsFindOptions ): Promise> => { diff --git a/packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts b/packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts index 0caa572238807..2239b94d7e2eb 100644 --- a/packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-browser-mocks/src/saved_objects_service.mock.ts @@ -19,6 +19,7 @@ const createStartContractMock = () => { bulkCreate: jest.fn(), bulkResolve: jest.fn(), bulkUpdate: jest.fn(), + bulkDelete: jest.fn(), delete: jest.fn(), bulkGet: jest.fn(), find: jest.fn(), diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/index.ts b/packages/core/saved-objects/core-saved-objects-server-internal/index.ts index caeb029e037f7..f7d6fa7918031 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/index.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/index.ts @@ -22,6 +22,7 @@ export { registerBulkCreateRoute } from './src/routes/bulk_create'; export { registerBulkGetRoute } from './src/routes/bulk_get'; export { registerBulkResolveRoute } from './src/routes/bulk_resolve'; export { registerBulkUpdateRoute } from './src/routes/bulk_update'; +export { registerBulkDeleteRoute } from './src/routes/bulk_delete'; export { registerCreateRoute } from './src/routes/create'; export { registerDeleteRoute } from './src/routes/delete'; export { registerExportRoute } from './src/routes/export'; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts new file mode 100644 index 0000000000000..f435eadebd066 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { schema } from '@kbn/config-schema'; +import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { InternalSavedObjectRouter } from '../internal_types'; +import { catchAndReturnBoomErrors } from './utils'; + +interface RouteDependencies { + coreUsageData: InternalCoreUsageDataSetup; +} + +export const registerBulkDeleteRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { + router.post( + { + path: '/_bulk_delete', + validate: { + body: schema.arrayOf( + schema.object({ + type: schema.string(), + id: schema.string(), + }) + ), + query: schema.object({ + force: schema.maybe(schema.boolean()), + }), + }, + }, + catchAndReturnBoomErrors(async (context, req, res) => { + const { force } = req.query; + const usageStatsClient = coreUsageData.getClient(); + usageStatsClient.incrementSavedObjectsBulkDelete({ request: req }).catch(() => {}); + + const { savedObjects } = await context.core; + + const statuses = await savedObjects.client.bulkDelete(req.body, { force }); + return res.ok({ body: statuses }); + }) + ); +}; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts index 528793e8539bd..89d5b41dd8885 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts @@ -23,6 +23,7 @@ import { registerUpdateRoute } from './update'; import { registerBulkGetRoute } from './bulk_get'; import { registerBulkCreateRoute } from './bulk_create'; import { registerBulkUpdateRoute } from './bulk_update'; +import { registerBulkDeleteRoute } from './bulk_delete'; import { registerExportRoute } from './export'; import { registerImportRoute } from './import'; import { registerResolveImportErrorsRoute } from './resolve_import_errors'; @@ -62,6 +63,7 @@ export function registerRoutes({ registerBulkCreateRoute(router, { coreUsageData }); registerBulkResolveRoute(router, { coreUsageData }); registerBulkUpdateRoute(router, { coreUsageData }); + registerBulkDeleteRoute(router, { coreUsageData }); registerExportRoute(router, { config, coreUsageData }); registerImportRoute(router, { config, coreUsageData }); registerResolveImportErrorsRoute(router, { config, coreUsageData }); diff --git a/packages/core/usage-data/core-usage-data-base-server-internal/src/usage_stats_client.ts b/packages/core/usage-data/core-usage-data-base-server-internal/src/usage_stats_client.ts index 3a603ebfdf5f0..735a4ab261658 100644 --- a/packages/core/usage-data/core-usage-data-base-server-internal/src/usage_stats_client.ts +++ b/packages/core/usage-data/core-usage-data-base-server-internal/src/usage_stats_client.ts @@ -43,6 +43,8 @@ export interface ICoreUsageStatsClient { incrementSavedObjectsBulkUpdate(options: BaseIncrementOptions): Promise; + incrementSavedObjectsBulkDelete(options: BaseIncrementOptions): Promise; + incrementSavedObjectsCreate(options: BaseIncrementOptions): Promise; incrementSavedObjectsDelete(options: BaseIncrementOptions): Promise; diff --git a/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.test.ts b/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.test.ts index f00341fdad0a7..1b7d332743697 100644 --- a/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.test.ts +++ b/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.test.ts @@ -20,6 +20,7 @@ import { BULK_CREATE_STATS_PREFIX, BULK_GET_STATS_PREFIX, BULK_UPDATE_STATS_PREFIX, + BULK_DELETE_STATS_PREFIX, CREATE_STATS_PREFIX, DELETE_STATS_PREFIX, FIND_STATS_PREFIX, @@ -452,6 +453,81 @@ describe('CoreUsageStatsClient', () => { }); }); + describe('#incrementSavedObjectsBulkDelete', () => { + it('does not throw an error if repository incrementCounter operation fails', async () => { + const { usageStatsClient, repositoryMock } = setup(); + repositoryMock.incrementCounter.mockRejectedValue(new Error('Oh no!')); + + const request = httpServerMock.createKibanaRequest(); + await expect( + usageStatsClient.incrementSavedObjectsBulkDelete({ + request, + } as BaseIncrementOptions) + ).resolves.toBeUndefined(); + expect(repositoryMock.incrementCounter).toHaveBeenCalled(); + }); + + it('handles falsy options appropriately', async () => { + const { usageStatsClient, repositoryMock } = setup(); + + const request = httpServerMock.createKibanaRequest(); + await usageStatsClient.incrementSavedObjectsBulkDelete({ + request, + } as BaseIncrementOptions); + expect(repositoryMock.incrementCounter).toHaveBeenCalledTimes(1); + expect(repositoryMock.incrementCounter).toHaveBeenCalledWith( + CORE_USAGE_STATS_TYPE, + CORE_USAGE_STATS_ID, + [ + `${BULK_DELETE_STATS_PREFIX}.total`, + `${BULK_DELETE_STATS_PREFIX}.namespace.default.total`, + `${BULK_DELETE_STATS_PREFIX}.namespace.default.kibanaRequest.no`, + ], + incrementOptions + ); + }); + + it('handles truthy options and the default namespace string appropriately', async () => { + const { usageStatsClient, repositoryMock } = setup(DEFAULT_NAMESPACE_STRING); + + const request = httpServerMock.createKibanaRequest({ headers: firstPartyRequestHeaders }); + await usageStatsClient.incrementSavedObjectsBulkDelete({ + request, + } as BaseIncrementOptions); + expect(repositoryMock.incrementCounter).toHaveBeenCalledTimes(1); + expect(repositoryMock.incrementCounter).toHaveBeenCalledWith( + CORE_USAGE_STATS_TYPE, + CORE_USAGE_STATS_ID, + [ + `${BULK_DELETE_STATS_PREFIX}.total`, + `${BULK_DELETE_STATS_PREFIX}.namespace.default.total`, + `${BULK_DELETE_STATS_PREFIX}.namespace.default.kibanaRequest.yes`, + ], + incrementOptions + ); + }); + + it('handles a non-default space appropriately', async () => { + const { usageStatsClient, repositoryMock } = setup('foo'); + + const request = httpServerMock.createKibanaRequest(); + await usageStatsClient.incrementSavedObjectsBulkDelete({ + request, + } as BaseIncrementOptions); + expect(repositoryMock.incrementCounter).toHaveBeenCalledTimes(1); + expect(repositoryMock.incrementCounter).toHaveBeenCalledWith( + CORE_USAGE_STATS_TYPE, + CORE_USAGE_STATS_ID, + [ + `${BULK_DELETE_STATS_PREFIX}.total`, + `${BULK_DELETE_STATS_PREFIX}.namespace.custom.total`, + `${BULK_DELETE_STATS_PREFIX}.namespace.custom.kibanaRequest.no`, + ], + incrementOptions + ); + }); + }); + describe('#incrementSavedObjectsDelete', () => { it('does not throw an error if repository incrementCounter operation fails', async () => { const { usageStatsClient, repositoryMock } = setup(); diff --git a/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.ts b/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.ts index 49c7333bea772..3bafa2e20e562 100644 --- a/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.ts +++ b/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_stats_client.ts @@ -25,6 +25,7 @@ export const BULK_CREATE_STATS_PREFIX = 'apiCalls.savedObjectsBulkCreate'; export const BULK_GET_STATS_PREFIX = 'apiCalls.savedObjectsBulkGet'; export const BULK_RESOLVE_STATS_PREFIX = 'apiCalls.savedObjectsBulkResolve'; export const BULK_UPDATE_STATS_PREFIX = 'apiCalls.savedObjectsBulkUpdate'; +export const BULK_DELETE_STATS_PREFIX = 'apiCalls.savedObjectsBulkDelete'; export const CREATE_STATS_PREFIX = 'apiCalls.savedObjectsCreate'; export const DELETE_STATS_PREFIX = 'apiCalls.savedObjectsDelete'; export const FIND_STATS_PREFIX = 'apiCalls.savedObjectsFind'; @@ -43,6 +44,7 @@ const ALL_COUNTER_FIELDS = [ ...getFieldsForCounter(BULK_GET_STATS_PREFIX), ...getFieldsForCounter(BULK_RESOLVE_STATS_PREFIX), ...getFieldsForCounter(BULK_UPDATE_STATS_PREFIX), + ...getFieldsForCounter(BULK_DELETE_STATS_PREFIX), ...getFieldsForCounter(CREATE_STATS_PREFIX), ...getFieldsForCounter(DELETE_STATS_PREFIX), ...getFieldsForCounter(FIND_STATS_PREFIX), @@ -114,6 +116,10 @@ export class CoreUsageStatsClient implements ICoreUsageStatsClient { await this.updateUsageStats([], BULK_UPDATE_STATS_PREFIX, options); } + public async incrementSavedObjectsBulkDelete(options: BaseIncrementOptions) { + await this.updateUsageStats([], BULK_DELETE_STATS_PREFIX, options); + } + public async incrementSavedObjectsCreate(options: BaseIncrementOptions) { await this.updateUsageStats([], CREATE_STATS_PREFIX, options); } diff --git a/packages/core/usage-data/core-usage-data-server-mocks/src/core_usage_stats_client.mock.ts b/packages/core/usage-data/core-usage-data-server-mocks/src/core_usage_stats_client.mock.ts index a6e76e33057dc..6da6da69f4962 100644 --- a/packages/core/usage-data/core-usage-data-server-mocks/src/core_usage_stats_client.mock.ts +++ b/packages/core/usage-data/core-usage-data-server-mocks/src/core_usage_stats_client.mock.ts @@ -15,6 +15,7 @@ const createUsageStatsClientMock = () => incrementSavedObjectsBulkGet: jest.fn().mockResolvedValue(null), incrementSavedObjectsBulkResolve: jest.fn().mockResolvedValue(null), incrementSavedObjectsBulkUpdate: jest.fn().mockResolvedValue(null), + incrementSavedObjectsBulkDelete: jest.fn().mockResolvedValue(null), incrementSavedObjectsCreate: jest.fn().mockResolvedValue(null), incrementSavedObjectsDelete: jest.fn().mockResolvedValue(null), incrementSavedObjectsFind: jest.fn().mockResolvedValue(null), diff --git a/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts b/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts index aef5b657fb6f7..279d5c68cd733 100644 --- a/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts +++ b/packages/core/usage-data/core-usage-data-server/src/core_usage_stats.ts @@ -42,6 +42,13 @@ export interface CoreUsageStats { 'apiCalls.savedObjectsBulkUpdate.namespace.custom.total'?: number; 'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.yes'?: number; 'apiCalls.savedObjectsBulkUpdate.namespace.custom.kibanaRequest.no'?: number; + 'apiCalls.savedObjectsBulkDelete.total'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.default.total'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.custom.total'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no'?: number; 'apiCalls.savedObjectsCreate.total'?: number; 'apiCalls.savedObjectsCreate.namespace.default.total'?: number; 'apiCalls.savedObjectsCreate.namespace.default.kibanaRequest.yes'?: number; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 0c6b68f79cebd..b8de0b6daa3b5 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -32,7 +32,7 @@ pageLoadAssetSize: embeddableEnhanced: 22107 enterpriseSearch: 35741 esUiShared: 326654 - eventAnnotation: 19500 + eventAnnotation: 20500 expressionError: 22127 expressionGauge: 25000 expressionHeatmap: 27505 diff --git a/packages/kbn-test/jest-preset.js b/packages/kbn-test/jest-preset.js index 35cef7b672a3d..3cb0ce86602cd 100644 --- a/packages/kbn-test/jest-preset.js +++ b/packages/kbn-test/jest-preset.js @@ -127,7 +127,7 @@ module.exports = { transformIgnorePatterns: [ // ignore all node_modules except monaco-editor and react-monaco-editor which requires babel transforms to handle dynamic import() // since ESM modules are not natively supported in Jest yet (https://github.com/facebook/jest/issues/4842) - '[/\\\\]node_modules(?![\\/\\\\](monaco-editor|react-monaco-editor|d3-interpolate|d3-color))[/\\\\].+\\.js$', + '[/\\\\]node_modules(?![\\/\\\\](byte-size|monaco-editor|react-monaco-editor|d3-interpolate|d3-color))[/\\\\].+\\.js$', 'packages/kbn-pm/dist/index.js', ], diff --git a/renovate.json b/renovate.json index 508cdcc684fc2..6eed31366c409 100644 --- a/renovate.json +++ b/renovate.json @@ -216,6 +216,15 @@ "labels": ["release_note:skip", "backport:skip"], "enabled": true, "prCreation": "immediate" + }, + { + "groupName": "TTY Output", + "matchPackageNames": ["xterm", "byte-size", "@types/byte-size"], + "reviewers": ["team:awp-viz"], + "matchBaseBranches": ["main"], + "labels": ["Team: AWP: Visualization", "release_note:skip", "backport:skip"], + "enabled": true, + "prCreation": "immediate" } ] } diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 67c29f0fb747c..6e72b1d2623cf 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -338,6 +338,9 @@ export type { SavedObjectsFindOptions, SavedObjectsFindOptionsReference, SavedObjectsPitParams, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponse, } from '@kbn/core-saved-objects-api-server'; export type { SavedObjectsServiceSetup, diff --git a/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts b/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts new file mode 100644 index 0000000000000..2536915f6f068 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import supertest from 'supertest'; +import { savedObjectsClientMock } from '../../../mocks'; +import type { ICoreUsageStatsClient } from '@kbn/core-usage-data-base-server-internal'; +import { + coreUsageStatsClientMock, + coreUsageDataServiceMock, +} from '@kbn/core-usage-data-server-mocks'; +import { setupServer } from './test_utils'; +import { + registerBulkDeleteRoute, + type InternalSavedObjectsRequestHandlerContext, +} from '@kbn/core-saved-objects-server-internal'; + +type SetupServerReturn = Awaited>; + +describe('POST /api/saved_objects/_bulk_delete', () => { + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + let handlerContext: SetupServerReturn['handlerContext']; + let savedObjectsClient: ReturnType; + let coreUsageStatsClient: jest.Mocked; + + beforeEach(async () => { + ({ server, httpSetup, handlerContext } = await setupServer()); + savedObjectsClient = handlerContext.savedObjects.client; + + savedObjectsClient.bulkDelete.mockResolvedValue({ + statuses: [], + }); + const router = + httpSetup.createRouter('/api/saved_objects/'); + coreUsageStatsClient = coreUsageStatsClientMock.create(); + coreUsageStatsClient.incrementSavedObjectsBulkDelete.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail + const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); + registerBulkDeleteRoute(router, { coreUsageData }); + + await server.start(); + }); + + afterEach(async () => { + await server.stop(); + }); + + it('formats successful response and records usage stats', async () => { + const clientResponse = { + statuses: [ + { + id: 'abc123', + type: 'index-pattern', + success: true, + }, + ], + }; + savedObjectsClient.bulkDelete.mockImplementation(() => Promise.resolve(clientResponse)); + + const result = await supertest(httpSetup.server.listener) + .post('/api/saved_objects/_bulk_delete') + .send([ + { + id: 'abc123', + type: 'index-pattern', + }, + ]) + .expect(200); + + expect(result.body).toEqual(clientResponse); + expect(coreUsageStatsClient.incrementSavedObjectsBulkDelete).toHaveBeenCalledWith({ + request: expect.anything(), + }); + }); + + it('calls upon savedObjectClient.bulkDelete with query options', async () => { + const docs = [ + { + id: 'abc123', + type: 'index-pattern', + }, + ]; + + await supertest(httpSetup.server.listener) + .post('/api/saved_objects/_bulk_delete') + .send(docs) + .query({ force: true }) + .expect(200); + + expect(savedObjectsClient.bulkDelete).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.bulkDelete).toHaveBeenCalledWith(docs, { force: true }); + }); +}); diff --git a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts index 7581e5f3639a2..f0fdc609d8915 100644 --- a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts +++ b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy.test.ts @@ -54,6 +54,17 @@ const registerSOTypes = (setup: InternalCoreSetup) => { }, namespaceType: 'single', }); + setup.savedObjects.registerType({ + name: 'my_bulk_delete_type', + hidden: false, + mappings: { + dynamic: false, + properties: { + title: { type: 'text' }, + }, + }, + namespaceType: 'single', + }); }; describe('404s from proxies', () => { @@ -124,6 +135,7 @@ describe('404s from proxies', () => { let repository: ISavedObjectsRepository; let myOtherType: SavedObject; const myOtherTypeDocs: SavedObject[] = []; + const myBulkDeleteTypeDocs: SavedObject[] = []; beforeAll(async () => { repository = start.savedObjects.createInternalRepository(); @@ -145,6 +157,19 @@ describe('404s from proxies', () => { overwrite: true, namespace: 'default', }); + + for (let i = 1; i < 11; i++) { + myBulkDeleteTypeDocs.push({ + type: 'my_bulk_delete_type', + id: `myOtherTypeId${i}`, + attributes: { title: `MyOtherTypeTitle${i}` }, + references: [], + }); + } + await repository.bulkCreate(myBulkDeleteTypeDocs, { + overwrite: true, + namespace: 'default', + }); }); beforeEach(() => { @@ -237,6 +262,18 @@ describe('404s from proxies', () => { ); }); + it('handles `bulkDelete` requests that are successful when the proxy passes through the product header', async () => { + const docsToDelete = myBulkDeleteTypeDocs; + const bulkDeleteDocs = docsToDelete.map((doc) => ({ + id: doc.id, + type: 'my_bulk_delete_type', + })); + + const docsFound = await repository.bulkDelete(bulkDeleteDocs, { force: false }); + expect(docsFound.statuses.length).toBeGreaterThan(0); + expect(docsFound.statuses[0].success).toBe(true); + }); + it('handles `bulkGet` requests that are successful when the proxy passes through the product header', async () => { const docsToGet = myOtherTypeDocs; const docsFound = await repository.bulkGet( diff --git a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts index 6f1c2c523226c..251c7608b6299 100644 --- a/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts +++ b/src/core/server/integration_tests/saved_objects/service/lib/repository_with_proxy_utils.ts @@ -122,7 +122,8 @@ export const declarePostMgetRoute = (hapiServer: Hapi.Server, hostname: string, if ( proxyInterrupt === 'bulkGetMyType' || proxyInterrupt === 'checkConficts' || - proxyInterrupt === 'internalBulkResolve' + proxyInterrupt === 'internalBulkResolve' || + proxyInterrupt === 'bulkDeleteMyDocs' ) { return proxyResponseHandler(h, hostname, port); } else { diff --git a/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.test.tsx b/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.test.tsx index edd1acc314e8e..ab5b340012125 100644 --- a/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.test.tsx +++ b/src/plugins/chart_expressions/expression_metric/public/components/metric_vis.test.tsx @@ -14,6 +14,7 @@ import { LayoutDirection, Metric, MetricElementEvent, + MetricWNumber, MetricWProgress, Settings, } from '@elastic/charts'; @@ -1124,7 +1125,7 @@ describe('MetricVisComponent', function () { value: primaryMetric, valueFormatter, extra, - } = component.find(Metric).props().data?.[0][0]!; + } = component.find(Metric).props().data?.[0][0]! as MetricWNumber; return { primary: valueFormatter(primaryMetric), secondary: extra?.props.children[1] }; }; diff --git a/src/plugins/chart_expressions/expression_xy/common/constants.ts b/src/plugins/chart_expressions/expression_xy/common/constants.ts index 8116f0146f19a..1c15be76bc509 100644 --- a/src/plugins/chart_expressions/expression_xy/common/constants.ts +++ b/src/plugins/chart_expressions/expression_xy/common/constants.ts @@ -123,6 +123,7 @@ export const AvailableReferenceLineIcons = { MAP_MARKER: 'mapMarker', PIN_FILLED: 'pinFilled', STAR_EMPTY: 'starEmpty', + STAR_FILLED: 'starFilled', TAG: 'tag', TRIANGLE: 'triangle', } as const; diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/icon.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/icon.ts index a74d4196f487d..652dbe168f58b 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/icon.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/icon.ts @@ -94,6 +94,12 @@ export const iconSet = [ value: AvailableReferenceLineIcons.STAR_EMPTY, label: i18n.translate('expressionXY.xyChart.iconSelect.starLabel', { defaultMessage: 'Star' }), }, + { + value: AvailableReferenceLineIcons.STAR_FILLED, + label: i18n.translate('expressionXY.xyChart.iconSelect.starFilledLabel', { + defaultMessage: 'Star filled', + }), + }, { value: AvailableReferenceLineIcons.TAG, label: i18n.translate('expressionXY.xyChart.iconSelect.tagIconLabel', { diff --git a/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx b/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx index b55f0fe714853..155d650583899 100644 --- a/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx +++ b/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx @@ -114,6 +114,7 @@ async function mountComponent(isTimeBased: boolean = false) { viewMode: VIEW_MODE.DOCUMENT_LEVEL, setDiscoverViewMode: jest.fn(), isTimeBased, + onResetChartHeight: jest.fn(), }; let instance: ReactWrapper = {} as ReactWrapper; diff --git a/src/plugins/discover/public/application/main/components/chart/discover_chart.tsx b/src/plugins/discover/public/application/main/components/chart/discover_chart.tsx index 4bc60e904bb84..4912022e08fdd 100644 --- a/src/plugins/discover/public/application/main/components/chart/discover_chart.tsx +++ b/src/plugins/discover/public/application/main/components/chart/discover_chart.tsx @@ -44,6 +44,7 @@ export function DiscoverChart({ interval, isTimeBased, appendHistogram, + onResetChartHeight, }: { className?: string; resetSavedSearch: () => void; @@ -56,6 +57,7 @@ export function DiscoverChart({ hideChart?: boolean; interval?: string; appendHistogram?: ReactElement; + onResetChartHeight?: () => void; }) { const { data, storage } = useDiscoverServices(); const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); @@ -113,13 +115,14 @@ export function DiscoverChart({ }, [data] ); - const panels = useChartPanels( + const panels = useChartPanels({ toggleHideChart, - (newInterval) => stateContainer.setAppState({ interval: newInterval }), - () => setShowChartOptionsPopover(false), + onChangeInterval: (newInterval) => stateContainer.setAppState({ interval: newInterval }), + closePopover: () => setShowChartOptionsPopover(false), + onResetChartHeight, hideChart, - interval - ); + interval, + }); return ( { test('useChartsPanel when hideChart is true', async () => { const { result } = renderHook(() => { - return useChartPanels(jest.fn(), jest.fn(), jest.fn(), true, 'auto'); + return useChartPanels({ + toggleHideChart: jest.fn(), + onChangeInterval: jest.fn(), + closePopover: jest.fn(), + onResetChartHeight: jest.fn(), + hideChart: true, + interval: 'auto', + }); }); const panels: EuiContextMenuPanelDescriptor[] = result.current; const panel0: EuiContextMenuPanelDescriptor = result.current[0]; expect(panels.length).toBe(1); + expect(panel0!.items).toHaveLength(1); expect(panel0!.items![0].icon).toBe('eye'); }); test('useChartsPanel when hideChart is false', async () => { const { result } = renderHook(() => { - return useChartPanels(jest.fn(), jest.fn(), jest.fn(), false, 'auto'); + return useChartPanels({ + toggleHideChart: jest.fn(), + onChangeInterval: jest.fn(), + closePopover: jest.fn(), + onResetChartHeight: jest.fn(), + hideChart: false, + interval: 'auto', + }); }); const panels: EuiContextMenuPanelDescriptor[] = result.current; const panel0: EuiContextMenuPanelDescriptor = result.current[0]; expect(panels.length).toBe(2); + expect(panel0!.items).toHaveLength(3); expect(panel0!.items![0].icon).toBe('eyeClosed'); + expect(panel0!.items![1].icon).toBe('refresh'); + }); + test('should not show reset chart height when onResetChartHeight is undefined', async () => { + const { result } = renderHook(() => { + return useChartPanels({ + toggleHideChart: jest.fn(), + onChangeInterval: jest.fn(), + closePopover: jest.fn(), + hideChart: false, + interval: 'auto', + }); + }); + const panel0: EuiContextMenuPanelDescriptor = result.current[0]; + expect(panel0!.items).toHaveLength(2); + expect(panel0!.items![0].icon).toBe('eyeClosed'); + }); + test('onResetChartHeight is called when the reset chart height button is clicked', async () => { + const onResetChartHeight = jest.fn(); + const { result } = renderHook(() => { + return useChartPanels({ + toggleHideChart: jest.fn(), + onChangeInterval: jest.fn(), + closePopover: jest.fn(), + onResetChartHeight, + hideChart: false, + interval: 'auto', + }); + }); + const panel0: EuiContextMenuPanelDescriptor = result.current[0]; + const resetChartHeightButton = panel0!.items![1]; + (resetChartHeightButton.onClick as Function)(); + expect(onResetChartHeight).toBeCalled(); }); }); diff --git a/src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts b/src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts index bbd670d217e58..f01c72aaee997 100644 --- a/src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts +++ b/src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts @@ -12,13 +12,21 @@ import type { } from '@elastic/eui'; import { search } from '@kbn/data-plugin/public'; -export function useChartPanels( - toggleHideChart: () => void, - onChangeInterval: (value: string) => void, - closePopover: () => void, - hideChart?: boolean, - interval?: string -) { +export function useChartPanels({ + toggleHideChart, + onChangeInterval, + closePopover, + onResetChartHeight, + hideChart, + interval, +}: { + toggleHideChart: () => void; + onChangeInterval: (value: string) => void; + closePopover: () => void; + onResetChartHeight?: () => void; + hideChart?: boolean; + interval?: string; +}) { const selectedOptionIdx = search.aggs.intervalOptions.findIndex((opt) => opt.val === interval); const intervalDisplay = selectedOptionIdx > -1 @@ -43,6 +51,20 @@ export function useChartPanels( }, ]; if (!hideChart) { + if (onResetChartHeight) { + mainPanelItems.push({ + name: i18n.translate('discover.resetChartHeight', { + defaultMessage: 'Reset to default height', + }), + icon: 'refresh', + onClick: () => { + onResetChartHeight(); + closePopover(); + }, + 'data-test-subj': 'discoverChartResetHeight', + }); + } + mainPanelItems.push({ name: i18n.translate('discover.timeIntervalWithValue', { defaultMessage: 'Time interval: {timeInterval}', diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index fbd58853d797c..fe6ac392c35a8 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -255,7 +255,6 @@ export function DiscoverLayout({ viewMode={viewMode} onDataViewCreated={onDataViewCreated} availableFields$={savedSearchData$.availableFields$} - persistDataView={persistDataView} /> diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx index 6b499aa62c430..ae433ee8ba38e 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx @@ -26,7 +26,11 @@ import { FetchStatus } from '../../../types'; import { Chart } from '../chart/point_series'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; -import { DiscoverMainContent, DiscoverMainContentProps } from './discover_main_content'; +import { + DiscoverMainContent, + DiscoverMainContentProps, + HISTOGRAM_HEIGHT_KEY, +} from './discover_main_content'; import { VIEW_MODE } from '@kbn/saved-search-plugin/public'; import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels'; import { euiThemeVars } from '@kbn/ui-theme'; @@ -36,21 +40,29 @@ import { setTimeout } from 'timers/promises'; import { DiscoverChart } from '../chart'; import { ReactWrapper } from 'enzyme'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; const mountComponent = async ({ isPlainRecord = false, hideChart = false, isTimeBased = true, + storage, }: { isPlainRecord?: boolean; hideChart?: boolean; isTimeBased?: boolean; + storage?: Storage; } = {}) => { - const services = discoverServiceMock; + let services = discoverServiceMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; + if (storage) { + services = { ...services, storage }; + } + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, @@ -188,67 +200,145 @@ describe('Discover main content component', () => { window.innerWidth = windowWidth; }); - it('should set the panels mode to DISCOVER_PANELS_MODE.RESIZABLE when viewing on medium screens and above', async () => { - const component = await mountComponent(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.m); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.RESIZABLE); - }); + describe('DISCOVER_PANELS_MODE', () => { + it('should set the panels mode to DISCOVER_PANELS_MODE.RESIZABLE when viewing on medium screens and above', async () => { + const component = await mountComponent(); + setWindowWidth(component, euiThemeVars.euiBreakpoints.m); + expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.RESIZABLE); + }); - it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED when viewing on small screens and below', async () => { - const component = await mountComponent(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); - }); + it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED when viewing on small screens and below', async () => { + const component = await mountComponent(); + setWindowWidth(component, euiThemeVars.euiBreakpoints.s); + expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); + }); - it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if hideChart is true', async () => { - const component = await mountComponent({ hideChart: true }); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); - }); + it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if hideChart is true', async () => { + const component = await mountComponent({ hideChart: true }); + expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); + }); - it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if isTimeBased is false', async () => { - const component = await mountComponent({ isTimeBased: false }); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); - }); + it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if isTimeBased is false', async () => { + const component = await mountComponent({ isTimeBased: false }); + expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); + }); - it('should set the panels mode to DISCOVER_PANELS_MODE.SINGLE if isPlainRecord is true', async () => { - const component = await mountComponent({ isPlainRecord: true }); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.SINGLE); - }); + it('should set the panels mode to DISCOVER_PANELS_MODE.SINGLE if isPlainRecord is true', async () => { + const component = await mountComponent({ isPlainRecord: true }); + expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.SINGLE); + }); - it('should set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is false', async () => { - const component = await mountComponent(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - const expectedHeight = component.find(DiscoverPanels).prop('initialTopPanelHeight'); - expect(component.find(DiscoverChart).childAt(0).getDOMNode()).toHaveStyle({ - height: `${expectedHeight}px`, + it('should set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is false', async () => { + const component = await mountComponent(); + setWindowWidth(component, euiThemeVars.euiBreakpoints.s); + const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight'); + expect(component.find(DiscoverChart).childAt(0).getDOMNode()).toHaveStyle({ + height: `${expectedHeight}px`, + }); }); - }); - it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is true', async () => { - const component = await mountComponent({ hideChart: true }); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - const expectedHeight = component.find(DiscoverPanels).prop('initialTopPanelHeight'); - expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({ - height: `${expectedHeight}px`, + it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is true', async () => { + const component = await mountComponent({ hideChart: true }); + setWindowWidth(component, euiThemeVars.euiBreakpoints.s); + const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight'); + expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({ + height: `${expectedHeight}px`, + }); }); - }); - it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and isTimeBased is false', async () => { - const component = await mountComponent({ isTimeBased: false }); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - const expectedHeight = component.find(DiscoverPanels).prop('initialTopPanelHeight'); - expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({ - height: `${expectedHeight}px`, + it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and isTimeBased is false', async () => { + const component = await mountComponent({ isTimeBased: false }); + setWindowWidth(component, euiThemeVars.euiBreakpoints.s); + const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight'); + expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({ + height: `${expectedHeight}px`, + }); + }); + + it('should pass undefined for onResetChartHeight to DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED', async () => { + const component = await mountComponent(); + expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeDefined(); + setWindowWidth(component, euiThemeVars.euiBreakpoints.s); + expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeUndefined(); }); }); - it('should show DocumentViewModeToggle when isPlainRecord is false', async () => { - const component = await mountComponent(); - expect(component.find(DocumentViewModeToggle).exists()).toBe(true); + describe('DocumentViewModeToggle', () => { + it('should show DocumentViewModeToggle when isPlainRecord is false', async () => { + const component = await mountComponent(); + expect(component.find(DocumentViewModeToggle).exists()).toBe(true); + }); + + it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => { + const component = await mountComponent({ isPlainRecord: true }); + expect(component.find(DocumentViewModeToggle).exists()).toBe(false); + }); }); - it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => { - const component = await mountComponent({ isPlainRecord: true }); - expect(component.find(DocumentViewModeToggle).exists()).toBe(false); + describe('topPanelHeight persistence', () => { + it('should try to get the initial topPanelHeight for DiscoverPanels from storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalGet = storage.get; + storage.get = jest.fn().mockImplementation(originalGet); + await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + }); + + it('should pass a default topPanelHeight to DiscoverPanels if no value is found in storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalGet = storage.get; + storage.get = jest.fn().mockImplementation(originalGet); + const component = await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(storage.get).toHaveReturnedWith(null); + expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBeGreaterThan(0); + }); + + it('should pass the stored topPanelHeight to DiscoverPanels if a value is found in storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const topPanelHeight = 123; + storage.get = jest.fn().mockImplementation(() => topPanelHeight); + const component = await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(storage.get).toHaveReturnedWith(topPanelHeight); + expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(topPanelHeight); + }); + + it('should update the topPanelHeight in storage and pass the new value to DiscoverPanels when the topPanelHeight changes', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalSet = storage.set; + storage.set = jest.fn().mockImplementation(originalSet); + const component = await mountComponent({ storage }); + const newTopPanelHeight = 123; + expect(component.find(DiscoverPanels).prop('topPanelHeight')).not.toBe(newTopPanelHeight); + act(() => { + component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight); + }); + component.update(); + expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); + expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(newTopPanelHeight); + }); + + it('should reset the topPanelHeight to the default when onResetChartHeight is called on DiscoverChart', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalSet = storage.set; + storage.set = jest.fn().mockImplementation(originalSet); + const component = await mountComponent({ storage }); + const defaultTopPanelHeight = component.find(DiscoverPanels).prop('topPanelHeight'); + const newTopPanelHeight = 123; + expect(component.find(DiscoverPanels).prop('topPanelHeight')).not.toBe(newTopPanelHeight); + act(() => { + component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight); + }); + component.update(); + expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); + expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(newTopPanelHeight); + act(() => { + component.find(DiscoverChart).prop('onResetChartHeight')!(); + }); + component.update(); + expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, defaultTopPanelHeight); + expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(defaultTopPanelHeight); + }); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index 747ccc9512a5f..68d91c9123a6d 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -15,7 +15,7 @@ import { useIsWithinBreakpoints, } from '@elastic/eui'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import React, { RefObject, useCallback, useMemo } from 'react'; +import React, { RefObject, useCallback, useMemo, useState } from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; import { METRIC_TYPE } from '@kbn/analytics'; import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal'; @@ -35,6 +35,8 @@ import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels'; const DiscoverChartMemoized = React.memo(DiscoverChart); const FieldStatisticsTableMemoized = React.memo(FieldStatisticsTable); +export const HISTOGRAM_HEIGHT_KEY = 'discover:histogramHeight'; + export interface DiscoverMainContentProps { isPlainRecord: boolean; dataView: DataView; @@ -74,7 +76,7 @@ export const DiscoverMainContent = ({ columns, resizeRef, }: DiscoverMainContentProps) => { - const { trackUiMetric } = useDiscoverServices(); + const { trackUiMetric, storage } = useDiscoverServices(); const setDiscoverViewMode = useCallback( (mode: VIEW_MODE) => { @@ -104,14 +106,36 @@ export const DiscoverMainContent = ({ const hideChart = state.hideChart || !isTimeBased; const showFixedPanels = useIsWithinBreakpoints(['xs', 's']) || isPlainRecord || hideChart; const { euiTheme } = useEuiTheme(); - const topPanelHeight = euiTheme.base * 12; + const defaultTopPanelHeight = euiTheme.base * 12; const minTopPanelHeight = euiTheme.base * 8; const minMainPanelHeight = euiTheme.base * 10; + const [topPanelHeight, setTopPanelHeight] = useState( + Number(storage.get(HISTOGRAM_HEIGHT_KEY)) || defaultTopPanelHeight + ); + + const storeTopPanelHeight = useCallback( + (newTopPanelHeight: number) => { + storage.set(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); + setTopPanelHeight(newTopPanelHeight); + }, + [storage] + ); + + const resetTopPanelHeight = useCallback( + () => storeTopPanelHeight(defaultTopPanelHeight), + [storeTopPanelHeight, defaultTopPanelHeight] + ); + + const onTopPanelHeightChange = useCallback( + (newTopPanelHeight: number) => storeTopPanelHeight(newTopPanelHeight), + [storeTopPanelHeight] + ); + const chartClassName = showFixedPanels && !hideChart ? css` - height: ${topPanelHeight}px; + height: ${defaultTopPanelHeight}px; ` : 'eui-fullHeight'; @@ -136,6 +160,9 @@ export const DiscoverMainContent = ({ interval={state.interval} isTimeBased={isTimeBased} appendHistogram={showFixedPanels ? : } + onResetChartHeight={ + panelsMode === DISCOVER_PANELS_MODE.RESIZABLE ? resetTopPanelHeight : undefined + } /> @@ -189,11 +216,12 @@ export const DiscoverMainContent = ({ className="dscPageContent__inner" mode={panelsMode} resizeRef={resizeRef} - initialTopPanelHeight={topPanelHeight} + topPanelHeight={topPanelHeight} minTopPanelHeight={minTopPanelHeight} minMainPanelHeight={minMainPanelHeight} topPanel={} mainPanel={} + onTopPanelHeightChange={onTopPanelHeightChange} /> ); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx index 60ba0038f1194..c136675494fb3 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx @@ -34,11 +34,12 @@ describe('Discover panels component', () => { ); }; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels.tsx b/src/plugins/discover/public/application/main/components/layout/discover_panels.tsx index 57ea08ee92c8b..b79d9fb96aaeb 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_panels.tsx @@ -20,11 +20,12 @@ export interface DiscoverPanelsProps { className?: string; mode: DISCOVER_PANELS_MODE; resizeRef: RefObject; - initialTopPanelHeight: number; + topPanelHeight: number; minTopPanelHeight: number; minMainPanelHeight: number; topPanel: ReactElement; mainPanel: ReactElement; + onTopPanelHeightChange: (height: number) => void; } const fixedModes = [DISCOVER_PANELS_MODE.SINGLE, DISCOVER_PANELS_MODE.FIXED]; @@ -33,11 +34,12 @@ export const DiscoverPanels = ({ className, mode, resizeRef, - initialTopPanelHeight, + topPanelHeight, minTopPanelHeight, minMainPanelHeight, topPanel, mainPanel, + onTopPanelHeightChange, }: DiscoverPanelsProps) => { const panelsProps = { className, topPanel, mainPanel }; @@ -46,9 +48,10 @@ export const DiscoverPanels = ({ ) : ( ); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx index 16c50a94b4656..c919504091c21 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx @@ -33,6 +33,7 @@ describe('Discover panels resizable', () => { topPanel = <>, mainPanel = <>, attachTo, + onTopPanelHeightChange = jest.fn(), }: { className?: string; resizeRef?: RefObject; @@ -42,16 +43,18 @@ describe('Discover panels resizable', () => { topPanel?: ReactElement; mainPanel?: ReactElement; attachTo?: HTMLElement; + onTopPanelHeightChange?: (height: number) => void; }) => { return mount( , attachTo ? { attachTo } : undefined ); @@ -95,7 +98,10 @@ describe('Discover panels resizable', () => { it('should set the correct heights of both panels when the panels are resized', () => { const initialTopPanelHeight = 200; - const component = mountComponent({ initialTopPanelHeight }); + const onTopPanelHeightChange = jest.fn((topPanelHeight) => { + component.setProps({ topPanelHeight }).update(); + }); + const component = mountComponent({ initialTopPanelHeight, onTopPanelHeightChange }); expectCorrectPanelSizes(component, containerHeight, initialTopPanelHeight); const newTopPanelSize = 30; const onPanelSizeChange = component @@ -106,7 +112,9 @@ describe('Discover panels resizable', () => { onPanelSizeChange({ [topPanelId]: newTopPanelSize }); }); forceRender(component); - expectCorrectPanelSizes(component, containerHeight, containerHeight * (newTopPanelSize / 100)); + const newTopPanelHeight = (newTopPanelSize / 100) * containerHeight; + expect(onTopPanelHeightChange).toHaveBeenCalledWith(newTopPanelHeight); + expectCorrectPanelSizes(component, containerHeight, newTopPanelHeight); }); it('should maintain the height of the top panel and resize the main panel when the container height changes', () => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx b/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx index 88a92b4380b76..b65da1eb0bf68 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx @@ -19,23 +19,24 @@ const pixelsToPercent = (containerHeight: number, pixels: number) => export const DiscoverPanelsResizable = ({ className, resizeRef, - initialTopPanelHeight, + topPanelHeight, minTopPanelHeight, minMainPanelHeight, topPanel, mainPanel, + onTopPanelHeightChange, }: { className?: string; resizeRef: RefObject; - initialTopPanelHeight: number; + topPanelHeight: number; minTopPanelHeight: number; minMainPanelHeight: number; topPanel: ReactElement; mainPanel: ReactElement; + onTopPanelHeightChange: (height: number) => void; }) => { const topPanelId = useGeneratedHtmlId({ prefix: 'topPanel' }); const { height: containerHeight } = useResizeObserver(resizeRef.current); - const [topPanelHeight, setTopPanelHeight] = useState(initialTopPanelHeight); const [panelSizes, setPanelSizes] = useState({ topPanelSize: 0, mainPanelSize: 0 }); // EuiResizableContainer doesn't work properly when used with react-reverse-portal and @@ -69,9 +70,13 @@ export const DiscoverPanelsResizable = ({ // the effect below to update the panel sizes. const onPanelSizeChange = useCallback( ({ [topPanelId]: topPanelSize }: { [key: string]: number }) => { - setTopPanelHeight(percentToPixels(containerHeight, topPanelSize)); + const newTopPanelHeight = percentToPixels(containerHeight, topPanelSize); + + if (newTopPanelHeight !== topPanelHeight) { + onTopPanelHeightChange(newTopPanelHeight); + } }, - [containerHeight, topPanelId] + [containerHeight, onTopPanelHeightChange, topPanelHeight, topPanelId] ); // This effect will update the panel sizes based on the top panel height whenever diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx index 5d1414ad488a3..ffb2ec7585ed5 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx @@ -88,7 +88,6 @@ async function getComponent({ onRemoveField: jest.fn(), showFieldStats, selected, - persistDataView: jest.fn(), state: { query: { query: '', language: 'lucene' }, filters: [], diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx index 8fb116f88bdc5..10138dec8b4cb 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx @@ -266,7 +266,6 @@ export interface DiscoverFieldProps { * Optionally show or hide field stats in the popover */ showFieldStats?: boolean; - persistDataView: (dataView: DataView) => Promise; /** * Discover App State @@ -293,7 +292,6 @@ function DiscoverFieldComponent({ onEditField, onDeleteField, showFieldStats, - persistDataView, state, contextualFields, }: DiscoverFieldProps) { @@ -520,7 +518,6 @@ function DiscoverFieldComponent({ multiFields={rawMultiFields} trackUiMetric={trackUiMetric} contextualFields={contextualFields} - persistDataView={persistDataView} /> ); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize.tsx index dccd664834b53..f60838d375b68 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_visualize.tsx @@ -9,12 +9,7 @@ import React, { useEffect, useState } from 'react'; import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; -import { VISUALIZE_GEO_FIELD_TRIGGER } from '@kbn/ui-actions-plugin/public'; -import { - getTriggerConstant, - triggerVisualizeActions, - VisualizeInformation, -} from './lib/visualize_trigger_utils'; +import { triggerVisualizeActions, VisualizeInformation } from './lib/visualize_trigger_utils'; import { getVisualizeInformation } from './lib/visualize_trigger_utils'; import { DiscoverFieldVisualizeInner } from './discover_field_visualize_inner'; @@ -24,11 +19,10 @@ interface Props { multiFields?: DataViewField[]; contextualFields: string[]; trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; - persistDataView: (dataView: DataView) => Promise; } export const DiscoverFieldVisualize: React.FC = React.memo( - ({ field, dataView, contextualFields, trackUiMetric, multiFields, persistDataView }) => { + ({ field, dataView, contextualFields, trackUiMetric, multiFields }) => { const [visualizeInfo, setVisualizeInfo] = useState(); useEffect(() => { @@ -47,20 +41,11 @@ export const DiscoverFieldVisualize: React.FC = React.memo( // regular link click. let the uiActions code handle the navigation and show popup if needed event.preventDefault(); - const trigger = getTriggerConstant(field.type); const triggerVisualization = (updatedDataView: DataView) => { trackUiMetric?.(METRIC_TYPE.CLICK, 'visualize_link_click'); triggerVisualizeActions(visualizeInfo.field, contextualFields, updatedDataView); }; - - if (trigger === VISUALIZE_GEO_FIELD_TRIGGER) { - const updatedDataView = await persistDataView(dataView); - if (updatedDataView) { - triggerVisualization(updatedDataView); - } - } else { - triggerVisualization(dataView); - } + triggerVisualization(dataView); }; return ( diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx index 8ee382b76832e..22d33215b1eaf 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx @@ -78,7 +78,6 @@ function getCompProps(): DiscoverSidebarProps { onDataViewCreated: jest.fn(), availableFields$, useNewFieldsApi: true, - persistDataView: jest.fn(), }; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx index 7ff64a1070c94..d7e227df94b8c 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx @@ -26,7 +26,7 @@ import useShallowCompareEffect from 'react-use/lib/useShallowCompareEffect'; import { isEqual } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; import { DataViewPicker } from '@kbn/unified-search-plugin/public'; -import { DataViewField, getFieldSubtypeMulti, type DataView } from '@kbn/data-views-plugin/public'; +import { DataViewField, getFieldSubtypeMulti } from '@kbn/data-views-plugin/public'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DiscoverField } from './discover_field'; import { DiscoverFieldSearch } from './discover_field_search'; @@ -93,7 +93,6 @@ export interface DiscoverSidebarProps extends Omit Promise; } export function DiscoverSidebarComponent({ @@ -118,7 +117,6 @@ export function DiscoverSidebarComponent({ createNewDataView, showDataViewPicker, state, - persistDataView, }: DiscoverSidebarProps) { const { uiSettings, dataViewFieldEditor } = useDiscoverServices(); const [fields, setFields] = useState(null); @@ -415,7 +413,6 @@ export function DiscoverSidebarComponent({ onEditField={editField} onDeleteField={deleteField} showFieldStats={showFieldStats} - persistDataView={persistDataView} state={state} contextualFields={columns} /> @@ -478,7 +475,6 @@ export function DiscoverSidebarComponent({ onEditField={editField} onDeleteField={deleteField} showFieldStats={showFieldStats} - persistDataView={persistDataView} state={state} contextualFields={columns} /> @@ -510,7 +506,6 @@ export function DiscoverSidebarComponent({ onEditField={editField} onDeleteField={deleteField} showFieldStats={showFieldStats} - persistDataView={persistDataView} state={state} contextualFields={columns} /> diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 201033050cc88..3d09302544755 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -175,7 +175,6 @@ function getCompProps(): DiscoverSidebarResponsiveProps { viewMode: VIEW_MODE.DOCUMENT_LEVEL, onDataViewCreated: jest.fn(), useNewFieldsApi: true, - persistDataView: jest.fn(), }; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index 07f4759c42b42..de3b30810859f 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -106,7 +106,6 @@ export interface DiscoverSidebarResponsiveProps { * list of available fields fetched from ES */ availableFields$: AvailableFields$; - persistDataView: (dataView: DataView) => Promise; } /** diff --git a/src/plugins/event_annotation/common/constants.ts b/src/plugins/event_annotation/common/constants.ts index 3338450b64ce5..3f3f9877b9786 100644 --- a/src/plugins/event_annotation/common/constants.ts +++ b/src/plugins/event_annotation/common/constants.ts @@ -19,6 +19,7 @@ export const AvailableAnnotationIcons = { MAP_MARKER: 'mapMarker', PIN_FILLED: 'pinFilled', STAR_EMPTY: 'starEmpty', + STAR_FILLED: 'starFilled', TAG: 'tag', TRIANGLE: 'triangle', } as const; diff --git a/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx b/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx index 58bf763a60b16..29d2bd893a87d 100644 --- a/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx +++ b/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { EuiProvider, EuiProviderProps } from '@elastic/eui'; +import type { EuiProviderProps } from '@elastic/eui'; +import { EuiProvider } from '@elastic/eui'; import createCache from '@emotion/cache'; import type { FC } from 'react'; import React, { useMemo } from 'react'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts index ce8e27f318cfd..28a921dd20162 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_collector.ts @@ -822,6 +822,46 @@ export function getCoreUsageCollector( 'How many times this API has been called by a non-Kibana client in a custom space.', }, }, + 'apiCalls.savedObjectsBulkDelete.total': { + type: 'long', + _meta: { description: 'How many times this API has been called.' }, + }, + 'apiCalls.savedObjectsBulkDelete.namespace.default.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in the Default space.' }, + }, + 'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in the Default space.', + }, + }, + 'apiCalls.savedObjectsBulkDelete.namespace.custom.total': { + type: 'long', + _meta: { description: 'How many times this API has been called in a custom space.' }, + }, + 'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by the Kibana client in a custom space.', + }, + }, + 'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no': { + type: 'long', + _meta: { + description: + 'How many times this API has been called by a non-Kibana client in a custom space.', + }, + }, // Saved Objects Management APIs 'apiCalls.savedObjectsImport.total': { type: 'long', diff --git a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_data.ts b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_data.ts index 36aac8ec0511a..2e5084f1b9ae5 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_data.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/core/core_usage_data.ts @@ -38,6 +38,13 @@ export interface CoreUsageStats { 'apiCalls.savedObjectsBulkResolve.namespace.custom.total'?: number; 'apiCalls.savedObjectsBulkResolve.namespace.custom.kibanaRequest.yes'?: number; 'apiCalls.savedObjectsBulkResolve.namespace.custom.kibanaRequest.no'?: number; + 'apiCalls.savedObjectsBulkDelete.total'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.default.total'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.custom.total'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes'?: number; + 'apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no'?: number; 'apiCalls.savedObjectsBulkUpdate.total'?: number; 'apiCalls.savedObjectsBulkUpdate.namespace.default.total'?: number; 'apiCalls.savedObjectsBulkUpdate.namespace.default.kibanaRequest.yes'?: number; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index b20d0a7c3f3bd..cc80adc4cb463 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -522,6 +522,10 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'observability:enableAwsLambdaMetrics': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, 'observability:apmProgressiveLoading': { type: 'keyword', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index f6aaf1258c818..924649351d988 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -141,6 +141,7 @@ export interface UsageStats { 'metrics:allowCheckingForFailedShards': boolean; 'observability:apmOperationsTab': boolean; 'observability:apmLabsButton': boolean; + 'observability:enableAwsLambdaMetrics': boolean; 'observability:apmProgressiveLoading': string; 'observability:apmServiceGroupMaxNumberOfServices': number; 'observability:apmServiceInventoryOptimizedSorting': boolean; diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 5d962699345b0..a1ddc4ee56040 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -7222,6 +7222,48 @@ "description": "How many times this API has been called by a non-Kibana client in a custom space." } }, + "apiCalls.savedObjectsBulkDelete.total": { + "type": "long", + "_meta": { + "description": "How many times this API has been called." + } + }, + "apiCalls.savedObjectsBulkDelete.namespace.default.total": { + "type": "long", + "_meta": { + "description": "How many times this API has been called in the Default space." + } + }, + "apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.yes": { + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in the Default space." + } + }, + "apiCalls.savedObjectsBulkDelete.namespace.default.kibanaRequest.no": { + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in the Default space." + } + }, + "apiCalls.savedObjectsBulkDelete.namespace.custom.total": { + "type": "long", + "_meta": { + "description": "How many times this API has been called in a custom space." + } + }, + "apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.yes": { + "type": "long", + "_meta": { + "description": "How many times this API has been called by the Kibana client in a custom space." + } + }, + "apiCalls.savedObjectsBulkDelete.namespace.custom.kibanaRequest.no": { + "type": "long", + "_meta": { + "description": "How many times this API has been called by a non-Kibana client in a custom space." + } + }, "apiCalls.savedObjectsImport.total": { "type": "long", "_meta": { @@ -8786,6 +8828,12 @@ "description": "Non-default value of setting." } }, + "observability:enableAwsLambdaMetrics": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "observability:apmProgressiveLoading": { "type": "keyword", "_meta": { @@ -10275,4 +10323,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/index.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/index.ts index c9e72040e26dd..5b92c0ab21668 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/index.ts @@ -33,7 +33,7 @@ const getConvertFnByType = (type: PANEL_TYPES) => { */ export const convertTSVBtoLensConfiguration = async (model: Panel, timeRange?: TimeRange) => { // Disables the option for not supported charts, for the string mode and for series with annotations - if (!model.use_kibana_indexes || (model.annotations && model.annotations.length > 0)) { + if (!model.use_kibana_indexes) { return null; } // Disables if model is invalid diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.test.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.test.ts index 656dc3a8c4290..f869ac64380c6 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.test.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.test.ts @@ -17,6 +17,12 @@ import { } from '../../convert'; import { getLayers } from './layers'; import { createPanel, createSeries } from '../../__mocks__'; +import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; + +jest.mock('uuid', () => ({ + v4: () => 'test-id', +})); describe('getLayers', () => { const dataSourceLayers: Record = [ @@ -200,6 +206,84 @@ describe('getLayers', () => { const panelWithPercentileRankMetric = createPanel({ series: [createSeries({ metrics: percentileRankMetrics })], }); + const panelWithSingleAnnotation = createPanel({ + annotations: [ + { + fields: 'geo.src,host', + template: 'Security Error from {{geo.src}} on {{host}}', + query_string: { + query: 'tags:error AND tags:security', + language: 'lucene', + }, + id: 'ann1', + color: 'rgba(211,49,21,0.7)', + time_field: 'timestamp', + icon: 'fa-asterisk', + ignore_global_filters: 1, + ignore_panel_filters: 1, + hidden: true, + index_pattern: { + id: 'test', + }, + }, + ], + series: [createSeries({ metrics: staticValueMetric })], + }); + const panelWithMultiAnnotations = createPanel({ + annotations: [ + { + fields: 'geo.src,host', + template: 'Security Error from {{geo.src}} on {{host}}', + query_string: { + query: 'tags:error AND tags:security', + language: 'lucene', + }, + id: 'ann1', + color: 'rgba(211,49,21,0.7)', + time_field: 'timestamp', + icon: 'fa-asterisk', + ignore_global_filters: 1, + ignore_panel_filters: 1, + hidden: true, + index_pattern: { + id: 'test', + }, + }, + { + query_string: { + query: 'tags: error AND tags: security', + language: 'kql', + }, + id: 'ann2', + color: 'blue', + time_field: 'timestamp', + icon: 'error-icon', + ignore_global_filters: 0, // todo test ignore when PR is r + ignore_panel_filters: 0, + index_pattern: { + id: 'test', + }, + }, + { + fields: 'category.keyword,price', + template: 'Will be ignored', + query_string: { + query: 'category.keyword:*', + language: 'kql', + }, + id: 'ann3', + color: 'red', + time_field: 'order_date', + icon: undefined, + ignore_global_filters: 1, + ignore_panel_filters: 1, + index_pattern: { + id: 'test2', + }, + }, + ], + series: [createSeries({ metrics: staticValueMetric })], + }); test.each<[string, [Record, Panel], Array>]>([ [ @@ -282,7 +366,159 @@ describe('getLayers', () => { }, ], ], - ])('should return %s', (_, input, expected) => { - expect(getLayers(...input)).toEqual(expected.map(expect.objectContaining)); + [ + 'annotation layer gets correct params and converts color, extraFields and icons', + [dataSourceLayersWithStatic, panelWithSingleAnnotation], + [ + { + layerType: 'referenceLine', + accessors: ['column-id-1'], + layerId: 'test-layer-1', + yConfig: [ + { + forAccessor: 'column-id-1', + axisMode: 'right', + color: '#68BC00', + fill: 'below', + }, + ], + }, + { + layerId: 'test-id', + layerType: 'annotations', + ignoreGlobalFilters: true, + annotations: [ + { + color: '#D33115', + extraFields: ['geo.src'], + filter: { + language: 'lucene', + query: 'tags:error AND tags:security', + type: 'kibana_query', + }, + icon: 'asterisk', + id: 'ann1', + isHidden: true, + key: { + type: 'point_in_time', + }, + label: 'Event', + timeField: 'timestamp', + type: 'query', + }, + ], + indexPatternId: 'test', + }, + ], + ], + [ + 'multiple annotations with different data views create separate layers', + [dataSourceLayersWithStatic, panelWithMultiAnnotations], + [ + { + layerType: 'referenceLine', + accessors: ['column-id-1'], + layerId: 'test-layer-1', + yConfig: [ + { + forAccessor: 'column-id-1', + axisMode: 'right', + color: '#68BC00', + fill: 'below', + }, + ], + }, + { + layerId: 'test-id', + layerType: 'annotations', + ignoreGlobalFilters: true, + annotations: [ + { + color: '#D33115', + extraFields: ['geo.src'], + filter: { + language: 'lucene', + query: 'tags:error AND tags:security', + type: 'kibana_query', + }, + icon: 'asterisk', + id: 'ann1', + isHidden: true, + key: { + type: 'point_in_time', + }, + label: 'Event', + timeField: 'timestamp', + type: 'query', + }, + { + color: '#0000FF', + filter: { + language: 'kql', + query: 'tags: error AND tags: security', + type: 'kibana_query', + }, + icon: 'triangle', + id: 'ann2', + key: { + type: 'point_in_time', + }, + label: 'Event', + timeField: 'timestamp', + type: 'query', + }, + ], + indexPatternId: 'test', + }, + { + layerId: 'test-id', + layerType: 'annotations', + ignoreGlobalFilters: true, + annotations: [ + { + color: '#FF0000', + extraFields: ['category.keyword', 'price'], + filter: { + language: 'kql', + query: 'category.keyword:*', + type: 'kibana_query', + }, + icon: 'triangle', + id: 'ann3', + key: { + type: 'point_in_time', + }, + label: 'Event', + timeField: 'order_date', + type: 'query', + }, + ], + indexPatternId: 'test2', + }, + ], + ], + ])('should return %s', async (_, input, expected) => { + const layers = await getLayers(...input, indexPatternsService as DataViewsPublicPluginStart); + expect(layers).toEqual(expected.map(expect.objectContaining)); }); }); + +const mockedIndices = [ + { + id: 'test', + title: 'test', + getFieldByName: (name: string) => ({ aggregatable: name !== 'host' }), + }, +] as unknown as DataView[]; + +const indexPatternsService = { + getDefault: jest.fn(() => Promise.resolve({ id: 'default', title: 'index' })), + get: jest.fn(() => Promise.resolve(mockedIndices[0])), + find: jest.fn((search: string, size: number) => { + if (size !== 1) { + // shouldn't request more than one data view since there is a significant performance penalty + throw new Error('trying to fetch too many data views'); + } + return Promise.resolve(mockedIndices || []); + }), +} as unknown as DataViewsPublicPluginStart; diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.ts index 0f411cc9d8fe6..064471e9fcfaf 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/configurations/xy/layers.ts @@ -7,13 +7,23 @@ */ import { + EventAnnotationConfig, FillTypes, + XYAnnotationsLayerConfig, XYLayerConfig, YAxisMode, } from '@kbn/visualizations-plugin/common/convert_to_lens'; import { PaletteOutput } from '@kbn/coloring'; +import { v4 } from 'uuid'; +import { transparentize } from '@elastic/eui'; +import Color from 'color'; +import { euiLightVars } from '@kbn/ui-theme'; +import { groupBy } from 'lodash'; +import { DataViewsPublicPluginStart, DataView } from '@kbn/data-plugin/public/data_views'; +import { fetchIndexPattern } from '../../../../../common/index_patterns_utils'; +import { ICON_TYPES_MAP } from '../../../../application/visualizations/constants'; import { SUPPORTED_METRICS } from '../../metrics'; -import type { Metric, Panel } from '../../../../../common/types'; +import type { Annotation, Metric, Panel } from '../../../../../common/types'; import { getSeriesAgg } from '../../series'; import { isPercentileRanksColumnWithMeta, @@ -51,11 +61,16 @@ function getColor( return seriesColor; } -export const getLayers = ( +function nonNullable(value: T): value is NonNullable { + return value !== null && value !== undefined; +} + +export const getLayers = async ( dataSourceLayers: Record, - model: Panel -): XYLayerConfig[] => { - return Object.keys(dataSourceLayers).map((key) => { + model: Panel, + dataViews: DataViewsPublicPluginStart +): Promise => { + const nonAnnotationsLayers: XYLayerConfig[] = Object.keys(dataSourceLayers).map((key) => { const series = model.series[parseInt(key, 10)]; const { metrics, seriesAgg } = getSeriesAgg(series.metrics); const dataSourceLayer = dataSourceLayers[parseInt(key, 10)]; @@ -112,4 +127,77 @@ export const getLayers = ( }; } }); + if (!model.annotations || !model.annotations.length) { + return nonAnnotationsLayers; + } + + const annotationsByIndexPattern = groupBy( + model.annotations, + (a) => typeof a.index_pattern === 'object' && 'id' in a.index_pattern && a.index_pattern.id + ); + + const annotationsLayers: Array = await Promise.all( + Object.entries(annotationsByIndexPattern).map(async ([indexPatternId, annotations]) => { + const convertedAnnotations: EventAnnotationConfig[] = []; + const { indexPattern } = (await fetchIndexPattern({ id: indexPatternId }, dataViews)) || {}; + + if (indexPattern) { + annotations.forEach((a: Annotation) => { + const lensAnnotation = convertAnnotation(a, indexPattern); + if (lensAnnotation) { + convertedAnnotations.push(lensAnnotation); + } + }); + return { + layerId: v4(), + layerType: 'annotations', + ignoreGlobalFilters: true, + annotations: convertedAnnotations, + indexPatternId, + }; + } + }) + ); + + return nonAnnotationsLayers.concat(...annotationsLayers.filter(nonNullable)); +}; + +const convertAnnotation = ( + annotation: Annotation, + dataView: DataView +): EventAnnotationConfig | undefined => { + if (annotation.query_string) { + const extraFields = annotation.fields + ? annotation.fields + ?.replace(/\s/g, '') + ?.split(',') + .map((field) => { + const dataViewField = dataView.getFieldByName(field); + return dataViewField && dataViewField.aggregatable ? field : undefined; + }) + .filter(nonNullable) + : undefined; + return { + type: 'query', + id: annotation.id, + label: 'Event', + key: { + type: 'point_in_time', + }, + color: new Color(transparentize(annotation.color || euiLightVars.euiColorAccent, 1)).hex(), + timeField: annotation.time_field, + icon: + annotation.icon && + ICON_TYPES_MAP[annotation.icon] && + typeof ICON_TYPES_MAP[annotation.icon] === 'string' + ? ICON_TYPES_MAP[annotation.icon] + : 'triangle', + filter: { + type: 'kibana_query', + ...annotation.query_string, + }, + extraFields, + isHidden: annotation.hidden, + }; + } }; diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/timeseries/index.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/timeseries/index.ts index c3f5900b35eb3..25cd1fa962d0d 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/timeseries/index.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/timeseries/index.ts @@ -9,6 +9,7 @@ import { parseTimeShift } from '@kbn/data-plugin/common'; import { Layer } from '@kbn/visualizations-plugin/common/convert_to_lens'; import uuid from 'uuid'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { Panel } from '../../../common/types'; import { PANEL_TYPES } from '../../../common/enums'; import { getDataViewsStart } from '../../services'; @@ -37,7 +38,7 @@ const excludeMetaFromLayers = (layers: Record): Record { - const dataViews = getDataViewsStart(); + const dataViews: DataViewsPublicPluginStart = getDataViewsStart(); const extendedLayers: Record = {}; const seriesNum = model.series.filter((series) => !series.hidden).length; @@ -96,9 +97,11 @@ export const convertToLens: ConvertTsvbToLensVisualization = async (model: Panel }; } + const configLayers = await getLayers(extendedLayers, model, dataViews); + return { type: 'lnsXY', layers: Object.values(excludeMetaFromLayers(extendedLayers)), - configuration: getConfiguration(model, getLayers(extendedLayers, model)), + configuration: getConfiguration(model, configLayers), }; }; diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/top_n/index.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/top_n/index.ts index 1afbd89e7027f..2622fadf5e753 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/top_n/index.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/top_n/index.ts @@ -79,9 +79,11 @@ export const convertToLens: ConvertTsvbToLensVisualization = async (model, timeR }; } + const configLayers = await getLayers(extendedLayers, model, dataViews); + return { type: 'lnsXY', layers: Object.values(excludeMetaFromLayers(extendedLayers)), - configuration: getConfiguration(model, getLayers(extendedLayers, model)), + configuration: getConfiguration(model, configLayers), }; }; diff --git a/src/plugins/visualizations/common/convert_to_lens/index.ts b/src/plugins/visualizations/common/convert_to_lens/index.ts index f47605f92719d..d336872cff6bb 100644 --- a/src/plugins/visualizations/common/convert_to_lens/index.ts +++ b/src/plugins/visualizations/common/convert_to_lens/index.ts @@ -8,3 +8,4 @@ export * from './types'; export * from './constants'; +export * from './utils'; diff --git a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts index b908ee2c5346b..4702ebae80826 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -9,6 +9,7 @@ import { HorizontalAlignment, Position, VerticalAlignment } from '@elastic/charts'; import { $Values } from '@kbn/utility-types'; import type { PaletteOutput } from '@kbn/coloring'; +import { KibanaQueryOutput } from '@kbn/data-plugin/common'; import { LegendSize } from '../../constants'; export const XYCurveTypes = { @@ -90,7 +91,33 @@ export interface XYReferenceLineLayerConfig { layerType: 'referenceLine'; } -export type XYLayerConfig = XYDataLayerConfig | XYReferenceLineLayerConfig; +export interface EventAnnotationConfig { + id: string; + filter: KibanaQueryOutput; + timeField?: string; + extraFields?: string[]; + label: string; + color?: string; + isHidden?: boolean; + icon?: string; + type: 'query'; + key: { + type: 'point_in_time'; + }; +} + +export interface XYAnnotationsLayerConfig { + layerId: string; + annotations: EventAnnotationConfig[]; + ignoreGlobalFilters: boolean; + layerType: 'annotations'; + indexPatternId: string; +} + +export type XYLayerConfig = + | XYDataLayerConfig + | XYReferenceLineLayerConfig + | XYAnnotationsLayerConfig; export interface AxesSettingsConfig { x: boolean; diff --git a/src/plugins/visualizations/common/convert_to_lens/utils.ts b/src/plugins/visualizations/common/convert_to_lens/utils.ts new file mode 100644 index 0000000000000..1beba70bc2a1b --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/utils.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { XYAnnotationsLayerConfig, XYLayerConfig } from './types'; + +export const isAnnotationsLayer = ( + layer: Pick +): layer is XYAnnotationsLayerConfig => layer.layerType === 'annotations'; diff --git a/test/api_integration/apis/saved_objects/bulk_delete.ts b/test/api_integration/apis/saved_objects/bulk_delete.ts new file mode 100644 index 0000000000000..5b5292b97ddde --- /dev/null +++ b/test/api_integration/apis/saved_objects/bulk_delete.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const kibanaServer = getService('kibanaServer'); + + describe('bulk_delete', () => { + before(async () => { + await kibanaServer.importExport.load( + 'test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' + ); + }); + after(async () => { + await kibanaServer.importExport.unload( + 'test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' + ); + }); + + it('should return 200 with individual responses when deleting many docs', async () => + await supertest + .post(`/api/saved_objects/_bulk_delete`) + .send([ + { + type: 'visualization', + id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', + }, + { + type: 'dashboard', + id: 'be3733a0-9efe-11e7-acb3-3dab96693fab', + }, + ]) + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + statuses: [ + { + success: true, + type: 'visualization', + id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', + }, + { + success: true, + type: 'dashboard', + id: 'be3733a0-9efe-11e7-acb3-3dab96693fab', + }, + ], + }); + })); + + it('should return generic 404 when deleting an unknown doc', async () => + await supertest + .post(`/api/saved_objects/_bulk_delete`) + .send([{ type: 'dashboard', id: 'not-a-real-id' }]) + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + statuses: [ + { + error: { + error: 'Not Found', + message: 'Saved object [dashboard/not-a-real-id] not found', + statusCode: 404, + }, + id: 'not-a-real-id', + type: 'dashboard', + success: false, + }, + ], + }); + })); + + it('should return the result of deleting valid and invalid objects in the same request', async () => + await supertest + .post(`/api/saved_objects/_bulk_delete`) + .send([ + { type: 'visualization', id: 'not-a-real-vis-id' }, + { + type: 'index-pattern', + id: '91200a00-9efd-11e7-acb3-3dab96693fab', + }, + ]) + .expect(200) + .then((resp) => { + expect(resp.body).to.eql({ + statuses: [ + { + error: { + error: 'Not Found', + message: 'Saved object [visualization/not-a-real-vis-id] not found', + statusCode: 404, + }, + id: 'not-a-real-vis-id', + type: 'visualization', + success: false, + }, + { + success: true, + type: 'index-pattern', + id: '91200a00-9efd-11e7-acb3-3dab96693fab', + }, + ], + }); + })); + }); +} diff --git a/test/api_integration/apis/saved_objects/index.ts b/test/api_integration/apis/saved_objects/index.ts index 44ee3d8d7d76b..c981add4540b3 100644 --- a/test/api_integration/apis/saved_objects/index.ts +++ b/test/api_integration/apis/saved_objects/index.ts @@ -11,6 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('saved_objects', () => { loadTestFile(require.resolve('./bulk_create')); + loadTestFile(require.resolve('./bulk_delete')); loadTestFile(require.resolve('./bulk_get')); loadTestFile(require.resolve('./bulk_update')); loadTestFile(require.resolve('./create')); diff --git a/versions.json b/versions.json index 11776f57850ee..5b70f97320e23 100644 --- a/versions.json +++ b/versions.json @@ -8,7 +8,7 @@ "currentMinor": true }, { - "version": "8.4.2", + "version": "8.4.3", "branch": "8.4", "currentMajor": true, "previousMinor": true diff --git a/x-pack/examples/triggers_actions_ui_example/public/plugin.tsx b/x-pack/examples/triggers_actions_ui_example/public/plugin.tsx index 57c752f140159..20683fb935126 100644 --- a/x-pack/examples/triggers_actions_ui_example/public/plugin.tsx +++ b/x-pack/examples/triggers_actions_ui_example/public/plugin.tsx @@ -142,7 +142,12 @@ export class TriggersActionsUiExamplePlugin useInternalFlyout, getRenderCellValue: () => (props: any) => { const value = props.data.find((d: any) => d.field === props.columnId)?.value ?? []; - return <>{value.length ? value.join() : '--'}; + + if (Array.isArray(value)) { + return <>{value.length ? value.join() : '--'}; + } + + return <>{value}; }, sort, }; diff --git a/x-pack/packages/ml/agg_utils/index.ts b/x-pack/packages/ml/agg_utils/index.ts index ac51405d0b8eb..cc7a426f94050 100644 --- a/x-pack/packages/ml/agg_utils/index.ts +++ b/x-pack/packages/ml/agg_utils/index.ts @@ -16,6 +16,7 @@ export type { AggCardinality, ChangePoint, ChangePointGroup, + ChangePointGroupHistogram, ChangePointHistogram, ChangePointHistogramItem, HistogramField, diff --git a/x-pack/packages/ml/agg_utils/src/types.ts b/x-pack/packages/ml/agg_utils/src/types.ts index 0128d5641bf24..a2c0d9f9a1569 100644 --- a/x-pack/packages/ml/agg_utils/src/types.ts +++ b/x-pack/packages/ml/agg_utils/src/types.ts @@ -87,6 +87,14 @@ export interface ChangePointHistogram extends FieldValuePair { histogram: ChangePointHistogramItem[]; } +/** + * Change point histogram data for a group of field/value pairs. + */ +export interface ChangePointGroupHistogram { + id: string; + histogram: ChangePointHistogramItem[]; +} + interface ChangePointGroupItem extends FieldValuePair { duplicate?: boolean; } @@ -95,6 +103,9 @@ interface ChangePointGroupItem extends FieldValuePair { * Tree leaves */ export interface ChangePointGroup { + id: string; group: ChangePointGroupItem[]; docCount: number; + pValue: number | null; + histogram?: ChangePointHistogramItem[]; } diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts index b5606543b04e5..7216f627ea783 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.test.ts @@ -721,6 +721,36 @@ Object { }, }, }, + count_connector_types_by_action_run_outcome_per_day: { + actionSavedObjects: { + connector_types: { + buckets: [ + { + key: '.slack', + outcome: { + count: { + buckets: [ + { key: 'success', doc_count: 12 }, + { key: 'failure', doc_count: 1 }, + ], + }, + }, + }, + { + key: '.email', + outcome: { + count: { + buckets: [ + { key: 'success', doc_count: 13 }, + { key: 'failure', doc_count: 2 }, + ], + }, + }, + }, + ], + }, + }, + }, }, } ); @@ -754,6 +784,16 @@ Object { __slack: 7, }, countTotal: 120, + countRunOutcomeByConnectorType: { + __email: { + failure: 2, + success: 13, + }, + __slack: { + failure: 1, + success: 12, + }, + }, hasErrors: false, }); }); @@ -775,6 +815,7 @@ Object { "countByType": Object {}, "countFailed": 0, "countFailedByType": Object {}, + "countRunOutcomeByConnectorType": Object {}, "countTotal": 0, "errorMessage": "oh no", "hasErrors": true, diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 1e2320e2b1a5d..15d2d6f4d12e5 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -7,6 +7,11 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { AggregationsTermsAggregateBase } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { + AvgActionRunOutcomeByConnectorTypeBucket, + parseActionRunOutcomeByConnectorTypesBucket, +} from './lib/parse_connector_type_bucket'; import { AlertHistoryEsIndexConnectorId } from '../../common'; import { ActionResult, PreConfiguredAction } from '../types'; @@ -395,7 +400,7 @@ export async function getInUseTotalCount( } } -function replaceFirstAndLastDotSymbols(strToReplace: string) { +export function replaceFirstAndLastDotSymbols(strToReplace: string) { const hasFirstSymbolDot = strToReplace.startsWith('.'); const appliedString = hasFirstSymbolDot ? strToReplace.replace('.', '__') : strToReplace; const hasLastSymbolDot = strToReplace.endsWith('.'); @@ -415,6 +420,7 @@ export async function getExecutionsPerDayCount( countFailedByType: Record; avgExecutionTime: number; avgExecutionTimeByType: Record; + countRunOutcomeByConnectorType: Record; }> { const scriptedMetric = { scripted_metric: { @@ -536,6 +542,35 @@ export async function getExecutionsPerDayCount( }, }, }, + count_connector_types_by_action_run_outcome_per_day: { + nested: { + path: 'kibana.saved_objects', + }, + aggs: { + actionSavedObjects: { + filter: { term: { 'kibana.saved_objects.type': 'action' } }, + aggs: { + connector_types: { + terms: { + field: 'kibana.saved_objects.type_id', + }, + aggs: { + outcome: { + reverse_nested: {}, + aggs: { + count: { + terms: { + field: 'event.outcome', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, }, }, }); @@ -564,6 +599,14 @@ export async function getExecutionsPerDayCount( {} ); + const aggsCountConnectorTypeByActionRun = actionResults.aggregations as { + count_connector_types_by_action_run_outcome_per_day: { + actionSavedObjects: { + connector_types: AggregationsTermsAggregateBase; + }; + }; + }; + return { hasErrors: false, countTotal: aggsExecutions.total, @@ -586,6 +629,10 @@ export async function getExecutionsPerDayCount( ), avgExecutionTime: aggsAvgExecutionTime, avgExecutionTimeByType, + countRunOutcomeByConnectorType: parseActionRunOutcomeByConnectorTypesBucket( + aggsCountConnectorTypeByActionRun.count_connector_types_by_action_run_outcome_per_day + .actionSavedObjects.connector_types.buckets + ), }; } catch (err) { const errorMessage = err && err.message ? err.message : err.toString(); @@ -601,6 +648,7 @@ export async function getExecutionsPerDayCount( countFailedByType: {}, avgExecutionTime: 0, avgExecutionTimeByType: {}, + countRunOutcomeByConnectorType: {}, }; } } diff --git a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts index f6e02b2e0fec9..f49525a4eec05 100644 --- a/x-pack/plugins/actions/server/usage/actions_usage_collector.ts +++ b/x-pack/plugins/actions/server/usage/actions_usage_collector.ts @@ -47,6 +47,13 @@ export function createActionsUsageCollector( count_actions_executions_failed_by_type_per_day: byTypeSchema, avg_execution_time_per_day: { type: 'long' }, avg_execution_time_by_type_per_day: byTypeSchema, + count_connector_types_by_action_run_outcome_per_day: { + DYNAMIC_KEY: { + success: { type: 'long' }, + failure: { type: 'long' }, + unknown: { type: 'long' }, + }, + }, }, fetch: async () => { try { @@ -77,6 +84,7 @@ export function createActionsUsageCollector( count_actions_executions_failed_by_type_per_day: {}, avg_execution_time_per_day: 0, avg_execution_time_by_type_per_day: {}, + count_connector_types_by_action_run_outcome_per_day: {}, }; } }, diff --git a/x-pack/plugins/actions/server/usage/lib/parse_connector_type_bucket.test.ts b/x-pack/plugins/actions/server/usage/lib/parse_connector_type_bucket.test.ts new file mode 100644 index 0000000000000..1241cddfeb55e --- /dev/null +++ b/x-pack/plugins/actions/server/usage/lib/parse_connector_type_bucket.test.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { parseActionRunOutcomeByConnectorTypesBucket } from './parse_connector_type_bucket'; + +describe('parseActionRunOutcomeByConnectorTypesBucket', () => { + test('should correctly parse connector type bucket results', () => { + expect( + parseActionRunOutcomeByConnectorTypesBucket([ + { + key: '.server-log', + doc_count: 78, + outcome: { + count: { + buckets: [ + { key: 'success', doc_count: 2 }, + { key: 'failure', doc_count: 1 }, + ], + }, + }, + }, + { + key: '.index', + doc_count: 42, + outcome: { + count: { + buckets: [ + { key: 'success', doc_count: 3 }, + { key: 'failure', doc_count: 4 }, + ], + }, + }, + }, + ]) + ).toEqual({ + __index: { + failure: 4, + success: 3, + }, + '__server-log': { + failure: 1, + success: 2, + }, + }); + }); + + test('should handle missing values', () => { + expect( + parseActionRunOutcomeByConnectorTypesBucket([ + { + key: '.server-log', + doc_count: 78, + outcome: { + count: { + // @ts-expect-error + buckets: [{ key: 'success', doc_count: 2 }, { key: 'failure' }], + }, + }, + }, + { + key: '.index', + outcome: { + // @ts-expect-error + count: {}, + }, + }, + ]) + ).toEqual({ + '__server-log': { + failure: 0, + success: 2, + }, + __index: {}, + }); + }); + + test('should handle empty input', () => { + expect(parseActionRunOutcomeByConnectorTypesBucket([])).toEqual({}); + }); + // + test('should handle undefined input', () => { + expect(parseActionRunOutcomeByConnectorTypesBucket(undefined)).toEqual({}); + }); +}); diff --git a/x-pack/plugins/actions/server/usage/lib/parse_connector_type_bucket.ts b/x-pack/plugins/actions/server/usage/lib/parse_connector_type_bucket.ts new file mode 100644 index 0000000000000..96e1610c635d8 --- /dev/null +++ b/x-pack/plugins/actions/server/usage/lib/parse_connector_type_bucket.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AggregationsBuckets } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { replaceFirstAndLastDotSymbols } from '../actions_telemetry'; + +export interface AvgActionRunOutcomeByConnectorTypeBucket { + key: string; + doc_count: number; // Not used for duration telemetry but can be helpful later. + outcome: { count: { buckets: Array<{ key: string; doc_count: number }> } }; +} + +export function parseActionRunOutcomeByConnectorTypesBucket( + connectorTypeBuckets: AggregationsBuckets = [] +) { + const connectorTypes = connectorTypeBuckets as AvgActionRunOutcomeByConnectorTypeBucket[]; + return connectorTypes.reduce((acc, connectorType) => { + const outcomes = connectorType.outcome?.count?.buckets ?? []; + return { + ...acc, + [replaceFirstAndLastDotSymbols(connectorType.key)]: outcomes.reduce((accBucket, bucket) => { + return { ...accBucket, [replaceFirstAndLastDotSymbols(bucket.key)]: bucket.doc_count || 0 }; + }, {}), + }; + }, {}); +} diff --git a/x-pack/plugins/actions/server/usage/task.ts b/x-pack/plugins/actions/server/usage/task.ts index 15f70529d3852..e8861b30ae8b4 100644 --- a/x-pack/plugins/actions/server/usage/task.ts +++ b/x-pack/plugins/actions/server/usage/task.ts @@ -130,6 +130,8 @@ export function telemetryTaskRunner( totalExecutionsPerDay.countFailedByType, avg_execution_time_per_day: totalExecutionsPerDay.avgExecutionTime, avg_execution_time_by_type_per_day: totalExecutionsPerDay.avgExecutionTimeByType, + count_connector_types_by_action_run_outcome_per_day: + totalExecutionsPerDay.countRunOutcomeByConnectorType, }, runAt: getNextMidnight(), }; diff --git a/x-pack/plugins/actions/server/usage/types.ts b/x-pack/plugins/actions/server/usage/types.ts index b58ac9c096f63..62ee11af72f8f 100644 --- a/x-pack/plugins/actions/server/usage/types.ts +++ b/x-pack/plugins/actions/server/usage/types.ts @@ -22,6 +22,7 @@ export interface ActionsUsage { count_actions_executions_by_type_per_day: Record; count_actions_executions_failed_per_day: number; count_actions_executions_failed_by_type_per_day: Record; + count_connector_types_by_action_run_outcome_per_day: Record>; avg_execution_time_per_day: number; avg_execution_time_by_type_per_day: Record; } diff --git a/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/actions.ts b/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/actions.ts index 938c765d8e0d2..e050946a489be 100644 --- a/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/actions.ts +++ b/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/actions.ts @@ -5,12 +5,18 @@ * 2.0. */ -import type { ChangePoint, ChangePointHistogram, ChangePointGroup } from '@kbn/ml-agg-utils'; +import type { + ChangePoint, + ChangePointHistogram, + ChangePointGroup, + ChangePointGroupHistogram, +} from '@kbn/ml-agg-utils'; export const API_ACTION_NAME = { ADD_CHANGE_POINTS: 'add_change_points', ADD_CHANGE_POINTS_HISTOGRAM: 'add_change_points_histogram', ADD_CHANGE_POINTS_GROUP: 'add_change_point_group', + ADD_CHANGE_POINTS_GROUP_HISTOGRAM: 'add_change_point_group_histogram', ADD_ERROR: 'add_error', RESET: 'reset', UPDATE_LOADING_STATE: 'update_loading_state', @@ -57,6 +63,20 @@ export function addChangePointsGroupAction(payload: ApiActionAddChangePointsGrou }; } +interface ApiActionAddChangePointsGroupHistogram { + type: typeof API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP_HISTOGRAM; + payload: ChangePointGroupHistogram[]; +} + +export function addChangePointsGroupHistogramAction( + payload: ApiActionAddChangePointsGroupHistogram['payload'] +): ApiActionAddChangePointsGroupHistogram { + return { + type: API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP_HISTOGRAM, + payload, + }; +} + interface ApiActionAddError { type: typeof API_ACTION_NAME.ADD_ERROR; payload: string; @@ -99,6 +119,7 @@ export type AiopsExplainLogRateSpikesApiAction = | ApiActionAddChangePoints | ApiActionAddChangePointsGroup | ApiActionAddChangePointsHistogram + | ApiActionAddChangePointsGroupHistogram | ApiActionAddError | ApiActionReset | ApiActionUpdateLoadingState; diff --git a/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/index.ts b/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/index.ts index dbc6be43766c6..5628b509980ad 100644 --- a/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/index.ts +++ b/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/index.ts @@ -8,6 +8,7 @@ export { addChangePointsAction, addChangePointsGroupAction, + addChangePointsGroupHistogramAction, addChangePointsHistogramAction, addErrorAction, resetAction, diff --git a/x-pack/plugins/aiops/common/api/stream_reducer.ts b/x-pack/plugins/aiops/common/api/stream_reducer.ts index ff275d1414e91..690db961f5121 100644 --- a/x-pack/plugins/aiops/common/api/stream_reducer.ts +++ b/x-pack/plugins/aiops/common/api/stream_reducer.ts @@ -51,6 +51,15 @@ export function streamReducer( return { ...state, changePoints }; case API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP: return { ...state, changePointsGroups: action.payload }; + case API_ACTION_NAME.ADD_CHANGE_POINTS_GROUP_HISTOGRAM: + const changePointsGroups = state.changePointsGroups.map((cpg) => { + const cpHistogram = action.payload.find((h) => h.id === cpg.id); + if (cpHistogram) { + cpg.histogram = cpHistogram.histogram; + } + return cpg; + }); + return { ...state, changePointsGroups }; case API_ACTION_NAME.ADD_ERROR: return { ...state, errors: [...state.errors, action.payload] }; case API_ACTION_NAME.RESET: diff --git a/x-pack/plugins/aiops/public/application/utils/query_utils.ts b/x-pack/plugins/aiops/public/application/utils/query_utils.ts index 85ad3d236a98e..1779b434df508 100644 --- a/x-pack/plugins/aiops/public/application/utils/query_utils.ts +++ b/x-pack/plugins/aiops/public/application/utils/query_utils.ts @@ -16,6 +16,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Query } from '@kbn/es-query'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import type { ChangePoint } from '@kbn/ml-agg-utils'; +import type { GroupTableItem } from '../../components/spike_analysis_table/spike_analysis_table_groups'; /* * Contains utility functions for building and processing queries. @@ -29,7 +30,8 @@ export function buildBaseFilterCriteria( latestMs?: number, query?: Query['query'], selectedChangePoint?: ChangePoint, - includeSelectedChangePoint = true + includeSelectedChangePoint = true, + selectedGroup?: GroupTableItem | null ): estypes.QueryDslQueryContainer[] { const filterCriteria = []; if (timeFieldName && earliestMs && latestMs) { @@ -48,10 +50,24 @@ export function buildBaseFilterCriteria( filterCriteria.push(query); } - if (selectedChangePoint && includeSelectedChangePoint) { - filterCriteria.push({ - term: { [selectedChangePoint.fieldName]: selectedChangePoint.fieldValue }, - }); + const groupFilter = []; + if (selectedGroup) { + const allItems = { ...selectedGroup.group, ...selectedGroup.repeatedValues }; + for (const fieldName in allItems) { + if (allItems.hasOwnProperty(fieldName)) { + groupFilter.push({ term: { [fieldName]: allItems[fieldName] } }); + } + } + } + + if (includeSelectedChangePoint) { + if (selectedChangePoint) { + filterCriteria.push({ + term: { [selectedChangePoint.fieldName]: selectedChangePoint.fieldValue }, + }); + } else if (selectedGroup) { + filterCriteria.push(...groupFilter); + } } else if (selectedChangePoint && !includeSelectedChangePoint) { filterCriteria.push({ bool: { @@ -62,6 +78,18 @@ export function buildBaseFilterCriteria( ], }, }); + } else if (selectedGroup && !includeSelectedChangePoint) { + filterCriteria.push({ + bool: { + must_not: [ + { + bool: { + filter: [...groupFilter], + }, + }, + ], + }, + }); } return filterCriteria; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx index 98d6053a8b6f6..a0fb825ee4064 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx @@ -32,6 +32,7 @@ import type { ApiExplainLogRateSpikes } from '../../../common/api'; import { SpikeAnalysisGroupsTable } from '../spike_analysis_table'; import { SpikeAnalysisTable } from '../spike_analysis_table'; +import { GroupTableItem } from '../spike_analysis_table/spike_analysis_table_groups'; const groupResultsMessage = i18n.translate( 'xpack.aiops.spikeAnalysisTable.groupedSwitchLabel.groupResults', @@ -56,6 +57,7 @@ interface ExplainLogRateSpikesAnalysisProps { onPinnedChangePoint?: (changePoint: ChangePoint | null) => void; onSelectedChangePoint?: (changePoint: ChangePoint | null) => void; selectedChangePoint?: ChangePoint; + onSelectedGroup?: (group: GroupTableItem | null) => void; } export const ExplainLogRateSpikesAnalysis: FC = ({ @@ -67,6 +69,7 @@ export const ExplainLogRateSpikesAnalysis: FC onPinnedChangePoint, onSelectedChangePoint, selectedChangePoint, + onSelectedGroup, }) => { const { http } = useAiopsAppContext(); const basePath = http.basePath.get() ?? ''; @@ -74,7 +77,7 @@ export const ExplainLogRateSpikesAnalysis: FC const [currentAnalysisWindowParameters, setCurrentAnalysisWindowParameters] = useState< WindowParameters | undefined >(); - const [groupResults, setGroupResults] = useState(true); + const [groupResults, setGroupResults] = useState(false); const onSwitchToggle = (e: { target: { checked: React.SetStateAction } }) => { setGroupResults(e.target.checked); @@ -106,6 +109,9 @@ export const ExplainLogRateSpikesAnalysis: FC // Start handler clears possibly hovered or pinned // change points on analysis refresh. function startHandler() { + // Reset grouping to false when restarting the analysis. + setGroupResults(false); + if (onPinnedChangePoint) { onPinnedChangePoint(null); } @@ -124,7 +130,7 @@ export const ExplainLogRateSpikesAnalysis: FC }, []); const groupTableItems = useMemo(() => { - const tableItems = data.changePointsGroups.map(({ group, docCount }, index) => { + const tableItems = data.changePointsGroups.map(({ id, group, docCount, histogram, pValue }) => { const sortedGroup = group.sort((a, b) => a.fieldName > b.fieldName ? 1 : b.fieldName > a.fieldName ? -1 : 0 ); @@ -141,10 +147,12 @@ export const ExplainLogRateSpikesAnalysis: FC }); return { - id: index, + id, docCount, + pValue, group: dedupedGroup, repeatedValues, + histogram, }; }); @@ -162,8 +170,7 @@ export const ExplainLogRateSpikesAnalysis: FC const groupItemCount = groupTableItems.reduce((p, c) => { return p + Object.keys(c.group).length; }, 0); - const foundGroups = - groupTableItems.length === 0 || (groupTableItems.length > 0 && groupItemCount > 0); + const foundGroups = groupTableItems.length > 0 && groupItemCount > 0; return (
@@ -178,6 +185,7 @@ export const ExplainLogRateSpikesAnalysis: FC {showSpikeAnalysisTable && foundGroups && ( onPinnedChangePoint={onPinnedChangePoint} onSelectedChangePoint={onSelectedChangePoint} selectedChangePoint={selectedChangePoint} + onSelectedGroup={onSelectedGroup} dataViewId={dataView.id} /> ) : null} diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx index bdc91175c2913..feff4f2e8211f 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_page.tsx @@ -37,6 +37,7 @@ import { SearchPanel } from '../search_panel'; import { restorableDefaults } from './explain_log_rate_spikes_app_state'; import { ExplainLogRateSpikesAnalysis } from './explain_log_rate_spikes_analysis'; +import type { GroupTableItem } from '../spike_analysis_table/spike_analysis_table_groups'; // TODO port to `@emotion/react` once `useEuiBreakpoint` is available https://github.com/elastic/eui/pull/6057 import './explain_log_rate_spikes_page.scss'; @@ -94,6 +95,7 @@ export const ExplainLogRateSpikesPage: FC = ({ const [pinnedChangePoint, setPinnedChangePoint] = useState(null); const [selectedChangePoint, setSelectedChangePoint] = useState(null); + const [selectedGroup, setSelectedGroup] = useState(null); // If a row is pinned, still overrule with a potentially hovered row. const currentSelectedChangePoint = useMemo(() => { @@ -116,7 +118,9 @@ export const ExplainLogRateSpikesPage: FC = ({ { currentDataView: dataView, currentSavedSearch }, aiopsListState, setGlobalState, - currentSelectedChangePoint + currentSelectedChangePoint, + undefined, + selectedGroup ); const { totalCount, documentCountStats, documentCountStatsCompare } = documentStats; @@ -167,6 +171,7 @@ export const ExplainLogRateSpikesPage: FC = ({ setWindowParameters(undefined); setPinnedChangePoint(null); setSelectedChangePoint(null); + setSelectedGroup(null); } return ( @@ -225,7 +230,9 @@ export const ExplainLogRateSpikesPage: FC = ({ clearSelectionHandler={clearSelection} documentCountStats={documentCountStats} documentCountStatsSplit={ - currentSelectedChangePoint ? documentCountStatsCompare : undefined + currentSelectedChangePoint || selectedGroup + ? documentCountStatsCompare + : undefined } totalCount={totalCount} changePoint={currentSelectedChangePoint} @@ -246,6 +253,7 @@ export const ExplainLogRateSpikesPage: FC = ({ onPinnedChangePoint={setPinnedChangePoint} onSelectedChangePoint={setSelectedChangePoint} selectedChangePoint={currentSelectedChangePoint} + onSelectedGroup={setSelectedGroup} /> )} {windowParameters === undefined && ( diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx index 8a65a938d38c9..35f3ba368be9a 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx @@ -32,6 +32,7 @@ import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transa const NARROW_COLUMN_WIDTH = '120px'; const ACTIONS_COLUMN_WIDTH = '60px'; +const NOT_AVAILABLE = '--'; const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50]; const DEFAULT_SORT_FIELD = 'pValue'; @@ -129,21 +130,21 @@ export const SpikeAnalysisTable: FC = ({ { 'data-test-subj': 'aiopsSpikeAnalysisTableColumnFieldName', field: 'fieldName', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldNameLabel', - { defaultMessage: 'Field name' } - ), + name: i18n.translate('xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.fieldNameLabel', { + defaultMessage: 'Field name', + }), sortable: true, + valign: 'top', }, { 'data-test-subj': 'aiopsSpikeAnalysisTableColumnFieldValue', field: 'fieldValue', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldValueLabel', - { defaultMessage: 'Field value' } - ), + name: i18n.translate('xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.fieldValueLabel', { + defaultMessage: 'Field value', + }), render: (_, { fieldValue }) => String(fieldValue).slice(0, 50), sortable: true, + valign: 'top', }, { 'data-test-subj': 'aiopsSpikeAnalysisTableColumnLogRate', @@ -153,7 +154,7 @@ export const SpikeAnalysisTable: FC = ({ = ({ > <> @@ -177,6 +178,17 @@ export const SpikeAnalysisTable: FC = ({ /> ), sortable: false, + valign: 'top', + }, + { + 'data-test-subj': 'aiopsSpikeAnalysisTableColumnDocCount', + width: NARROW_COLUMN_WIDTH, + field: 'doc_count', + name: i18n.translate('xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.docCountLabel', { + defaultMessage: 'Doc count', + }), + sortable: true, + valign: 'top', }, { 'data-test-subj': 'aiopsSpikeAnalysisTableColumnPValue', @@ -186,7 +198,7 @@ export const SpikeAnalysisTable: FC = ({ = ({ > <> ), - render: (pValue: number) => pValue.toPrecision(3), + render: (pValue: number | null) => pValue?.toPrecision(3) ?? NOT_AVAILABLE, sortable: true, + valign: 'top', }, { 'data-test-subj': 'aiopsSpikeAnalysisTableColumnImpact', @@ -213,7 +226,7 @@ export const SpikeAnalysisTable: FC = ({ = ({ > <> @@ -229,10 +242,12 @@ export const SpikeAnalysisTable: FC = ({ ), render: (_, { pValue }) => { + if (!pValue) return NOT_AVAILABLE; const label = getFailedTransactionsCorrelationImpactLabel(pValue); return label ? {label.impact} : null; }, sortable: true, + valign: 'top', }, { 'data-test-subj': 'aiOpsSpikeAnalysisTableColumnAction', @@ -258,6 +273,7 @@ export const SpikeAnalysisTable: FC = ({ }, ], width: ACTIONS_COLUMN_WIDTH, + valign: 'top', }, ]; diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_expanded_row.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_expanded_row.tsx deleted file mode 100644 index 367e5f32c695b..0000000000000 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_expanded_row.tsx +++ /dev/null @@ -1,357 +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, useCallback, useMemo, useState } from 'react'; -import { sortBy } from 'lodash'; - -import { - EuiBadge, - EuiBasicTable, - EuiBasicTableColumn, - EuiIcon, - EuiTableSortingType, - EuiToolTip, -} from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { escapeKuery } from '@kbn/es-query'; -import type { ChangePoint } from '@kbn/ml-agg-utils'; - -import { SEARCH_QUERY_LANGUAGE } from '../../application/utils/search_utils'; -import { useEuiTheme } from '../../hooks/use_eui_theme'; -import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; - -import { MiniHistogram } from '../mini_histogram'; - -import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transactions_correlation_impact_label'; - -const NARROW_COLUMN_WIDTH = '120px'; -const ACTIONS_COLUMN_WIDTH = '60px'; -const NOT_AVAILABLE = '--'; - -const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50]; -const DEFAULT_SORT_FIELD = 'pValue'; -const DEFAULT_SORT_DIRECTION = 'asc'; -const viewInDiscoverMessage = i18n.translate( - 'xpack.aiops.spikeAnalysisTable.linksMenu.viewInDiscover', - { - defaultMessage: 'View in Discover', - } -); - -interface SpikeAnalysisTableExpandedRowProps { - changePoints: ChangePoint[]; - dataViewId?: string; - loading: boolean; - onPinnedChangePoint?: (changePoint: ChangePoint | null) => void; - onSelectedChangePoint?: (changePoint: ChangePoint | null) => void; - selectedChangePoint?: ChangePoint; -} - -export const SpikeAnalysisTableExpandedRow: FC = ({ - changePoints, - dataViewId, - loading, - onPinnedChangePoint, - onSelectedChangePoint, - selectedChangePoint, -}) => { - const euiTheme = useEuiTheme(); - - const [pageIndex, setPageIndex] = useState(0); - const [pageSize, setPageSize] = useState(10); - const [sortField, setSortField] = useState(DEFAULT_SORT_FIELD); - const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>(DEFAULT_SORT_DIRECTION); - - const { application, share, data } = useAiopsAppContext(); - - const discoverLocator = useMemo( - () => share.url.locators.get('DISCOVER_APP_LOCATOR'), - [share.url.locators] - ); - - const discoverUrlError = useMemo(() => { - if (!application.capabilities.discover?.show) { - const discoverNotEnabled = i18n.translate( - 'xpack.aiops.spikeAnalysisTable.discoverNotEnabledErrorMessage', - { - defaultMessage: 'Discover is not enabled', - } - ); - - return discoverNotEnabled; - } - if (!discoverLocator) { - const discoverLocatorMissing = i18n.translate( - 'xpack.aiops.spikeAnalysisTable.discoverLocatorMissingErrorMessage', - { - defaultMessage: 'No locator for Discover detected', - } - ); - - return discoverLocatorMissing; - } - if (!dataViewId) { - const autoGeneratedDiscoverLinkError = i18n.translate( - 'xpack.aiops.spikeAnalysisTable.autoGeneratedDiscoverLinkErrorMessage', - { - defaultMessage: 'Unable to link to Discover; no data view exists for this index', - } - ); - - return autoGeneratedDiscoverLinkError; - } - }, [application.capabilities.discover?.show, dataViewId, discoverLocator]); - - const generateDiscoverUrl = async (changePoint: ChangePoint) => { - if (discoverLocator !== undefined) { - const url = await discoverLocator.getRedirectUrl({ - indexPatternId: dataViewId, - timeRange: data.query.timefilter.timefilter.getTime(), - filters: data.query.filterManager.getFilters(), - query: { - language: SEARCH_QUERY_LANGUAGE.KUERY, - query: `${escapeKuery(changePoint.fieldName)}:${escapeKuery( - String(changePoint.fieldValue) - )}`, - }, - }); - - return url; - } - }; - - const columns: Array> = [ - { - 'data-test-subj': 'aiopsSpikeAnalysisTableColumnFieldName', - field: 'fieldName', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldNameLabel', - { defaultMessage: 'Field name' } - ), - sortable: true, - }, - { - 'data-test-subj': 'aiopsSpikeAnalysisTableColumnFieldValue', - field: 'fieldValue', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.fieldValueLabel', - { defaultMessage: 'Field value' } - ), - render: (_, { fieldValue }) => String(fieldValue).slice(0, 50), - sortable: true, - }, - { - 'data-test-subj': 'aiopsSpikeAnalysisTableColumnLogRate', - width: NARROW_COLUMN_WIDTH, - field: 'pValue', - name: ( - - <> - - - - - ), - render: (_, { histogram, fieldName, fieldValue }) => { - if (!histogram) return NOT_AVAILABLE; - return ( - - ); - }, - sortable: false, - }, - { - 'data-test-subj': 'aiopsSpikeAnalysisTableColumnPValue', - width: NARROW_COLUMN_WIDTH, - field: 'pValue', - name: ( - - <> - - - - - ), - render: (pValue: number) => pValue?.toPrecision(3) ?? NOT_AVAILABLE, - sortable: true, - }, - { - 'data-test-subj': 'aiopsSpikeAnalysisTableColumnImpact', - width: NARROW_COLUMN_WIDTH, - field: 'pValue', - name: ( - - <> - - - - - ), - render: (_, { pValue }) => { - if (!pValue) return NOT_AVAILABLE; - const label = getFailedTransactionsCorrelationImpactLabel(pValue); - return label ? {label.impact} : null; - }, - sortable: true, - }, - { - 'data-test-subj': 'aiOpsSpikeAnalysisTableColumnAction', - name: i18n.translate('xpack.aiops.spikeAnalysisTable.actionsColumnName', { - defaultMessage: 'Actions', - }), - actions: [ - { - name: () => ( - - - - ), - description: viewInDiscoverMessage, - type: 'button', - onClick: async (changePoint) => { - const openInDiscoverUrl = await generateDiscoverUrl(changePoint); - if (typeof openInDiscoverUrl === 'string') { - await application.navigateToUrl(openInDiscoverUrl); - } - }, - enabled: () => discoverUrlError === undefined, - }, - ], - width: ACTIONS_COLUMN_WIDTH, - }, - ]; - - const onChange = useCallback((tableSettings) => { - const { index, size } = tableSettings.page; - const { field, direction } = tableSettings.sort; - - setPageIndex(index); - setPageSize(size); - setSortField(field); - setSortDirection(direction); - }, []); - - const { pagination, pageOfItems, sorting } = useMemo(() => { - const pageStart = pageIndex * pageSize; - const itemCount = changePoints?.length ?? 0; - - let items: ChangePoint[] = changePoints ?? []; - items = sortBy(changePoints, (item) => { - if (item && typeof item[sortField] === 'string') { - // @ts-ignore Object is possibly null or undefined - return item[sortField].toLowerCase(); - } - return item[sortField]; - }); - items = sortDirection === 'asc' ? items : items.reverse(); - - return { - pageOfItems: items.slice(pageStart, pageStart + pageSize), - pagination: { - pageIndex, - pageSize, - totalItemCount: itemCount, - pageSizeOptions: PAGINATION_SIZE_OPTIONS, - }, - sorting: { - sort: { - field: sortField, - direction: sortDirection, - }, - }, - }; - }, [pageIndex, pageSize, sortField, sortDirection, changePoints]); - - // Don't pass on the `loading` state to the table itself because - // it disables hovering events. Because the mini histograms take a while - // to load, hovering would not update the main chart. Instead, - // the loading state is shown by the progress bar on the outer component level. - // The outer component also will display a prompt when no data was returned - // running the analysis and will hide this table. - - return ( - } - rowProps={(changePoint) => { - return { - 'data-test-subj': `aiopsSpikeAnalysisTableRow row-${changePoint.fieldName}-${changePoint.fieldValue}`, - onClick: () => { - if (onPinnedChangePoint) { - onPinnedChangePoint(changePoint); - } - }, - onMouseEnter: () => { - if (onSelectedChangePoint) { - onSelectedChangePoint(changePoint); - } - }, - onMouseLeave: () => { - if (onSelectedChangePoint) { - onSelectedChangePoint(null); - } - }, - style: - selectedChangePoint && - selectedChangePoint.fieldValue === changePoint.fieldValue && - selectedChangePoint.fieldName === changePoint.fieldName - ? { - backgroundColor: euiTheme.euiColorLightestShade, - } - : null, - }; - }} - /> - ); -}; diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx index 7b61911a96384..a7503e7d49111 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table_groups.tsx @@ -13,25 +13,50 @@ import { EuiBasicTable, EuiBasicTableColumn, EuiButtonIcon, + EuiIcon, EuiScreenReaderOnly, EuiSpacer, EuiTableSortingType, + EuiToolTip, RIGHT_ALIGNMENT, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { escapeKuery } from '@kbn/es-query'; +import { FormattedMessage } from '@kbn/i18n-react'; import type { ChangePoint } from '@kbn/ml-agg-utils'; + +import { SEARCH_QUERY_LANGUAGE } from '../../application/utils/search_utils'; import { useEuiTheme } from '../../hooks/use_eui_theme'; -import { SpikeAnalysisTableExpandedRow } from './spike_analysis_table_expanded_row'; +import { useAiopsAppContext } from '../../hooks/use_aiops_app_context'; + +import { MiniHistogram } from '../mini_histogram'; + +import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transactions_correlation_impact_label'; +import { SpikeAnalysisTable } from './spike_analysis_table'; + +const NARROW_COLUMN_WIDTH = '120px'; +const EXPAND_COLUMN_WIDTH = '40px'; +const ACTIONS_COLUMN_WIDTH = '60px'; +const NOT_AVAILABLE = '--'; const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50]; -const DEFAULT_SORT_FIELD = 'docCount'; -const DEFAULT_SORT_DIRECTION = 'desc'; -interface GroupTableItem { - id: number; +const DEFAULT_SORT_FIELD = 'pValue'; +const DEFAULT_SORT_DIRECTION = 'asc'; +const viewInDiscoverMessage = i18n.translate( + 'xpack.aiops.spikeAnalysisTable.linksMenu.viewInDiscover', + { + defaultMessage: 'View in Discover', + } +); + +export interface GroupTableItem { + id: string; docCount: number; - group: Record; - repeatedValues: Record; + pValue: number | null; + group: Record; + repeatedValues: Record; + histogram: ChangePoint['histogram']; } interface SpikeAnalysisTableProps { @@ -42,6 +67,7 @@ interface SpikeAnalysisTableProps { onPinnedChangePoint?: (changePoint: ChangePoint | null) => void; onSelectedChangePoint?: (changePoint: ChangePoint | null) => void; selectedChangePoint?: ChangePoint; + onSelectedGroup?: (group: GroupTableItem | null) => void; } export const SpikeAnalysisGroupsTable: FC = ({ @@ -52,6 +78,7 @@ export const SpikeAnalysisGroupsTable: FC = ({ onPinnedChangePoint, onSelectedChangePoint, selectedChangePoint, + onSelectedGroup, }) => { const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(10); @@ -91,7 +118,7 @@ export const SpikeAnalysisGroupsTable: FC = ({ } itemIdToExpandedRowMapValues[item.id] = ( - = ({ setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); }; + const { application, share, data } = useAiopsAppContext(); + + const discoverLocator = useMemo( + () => share.url.locators.get('DISCOVER_APP_LOCATOR'), + [share.url.locators] + ); + + const discoverUrlError = useMemo(() => { + if (!application.capabilities.discover?.show) { + const discoverNotEnabled = i18n.translate( + 'xpack.aiops.spikeAnalysisTable.discoverNotEnabledErrorMessage', + { + defaultMessage: 'Discover is not enabled', + } + ); + + return discoverNotEnabled; + } + if (!discoverLocator) { + const discoverLocatorMissing = i18n.translate( + 'xpack.aiops.spikeAnalysisTable.discoverLocatorMissingErrorMessage', + { + defaultMessage: 'No locator for Discover detected', + } + ); + + return discoverLocatorMissing; + } + if (!dataViewId) { + const autoGeneratedDiscoverLinkError = i18n.translate( + 'xpack.aiops.spikeAnalysisTable.autoGeneratedDiscoverLinkErrorMessage', + { + defaultMessage: 'Unable to link to Discover; no data view exists for this index', + } + ); + + return autoGeneratedDiscoverLinkError; + } + }, [application.capabilities.discover?.show, dataViewId, discoverLocator]); + + const generateDiscoverUrl = async (groupTableItem: GroupTableItem) => { + if (discoverLocator !== undefined) { + const url = await discoverLocator.getRedirectUrl({ + indexPatternId: dataViewId, + timeRange: data.query.timefilter.timefilter.getTime(), + filters: data.query.filterManager.getFilters(), + query: { + language: SEARCH_QUERY_LANGUAGE.KUERY, + query: [ + ...Object.entries(groupTableItem.group).map( + ([fieldName, fieldValue]) => + `${escapeKuery(fieldName)}:${escapeKuery(String(fieldValue))}` + ), + ...Object.entries(groupTableItem.repeatedValues).map( + ([fieldName, fieldValue]) => + `${escapeKuery(fieldName)}:${escapeKuery(String(fieldValue))}` + ), + ].join(' AND '), + }, + }); + + return url; + } + }; + const columns: Array> = [ { align: RIGHT_ALIGNMENT, - width: '40px', + width: EXPAND_COLUMN_WIDTH, isExpander: true, name: ( @@ -118,18 +210,32 @@ export const SpikeAnalysisGroupsTable: FC = ({ toggleDetails(item)} - aria-label={itemIdToExpandedRowMap[item.id] ? 'Collapse' : 'Expand'} + aria-label={ + itemIdToExpandedRowMap[item.id] + ? i18n.translate( + 'xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.collapseAriaLabel', + { + defaultMessage: 'Collapse', + } + ) + : i18n.translate( + 'xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.expandAriaLabel', + { + defaultMessage: 'Expand', + } + ) + } iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'} /> ), + valign: 'top', }, { 'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnGroup', field: 'group', - name: i18n.translate( - 'xpack.aiops.correlations.failedTransactions.correlationsTable.groupLabel', - { defaultMessage: 'Group' } - ), + name: i18n.translate('xpack.aiops.explainLogRateSpikes.spikeAnalysisTableGroups.groupLabel', { + defaultMessage: 'Group', + }), render: (_, { group, repeatedValues }) => { const valuesBadges = []; for (const fieldName in group) { @@ -159,7 +265,11 @@ export const SpikeAnalysisGroupsTable: FC = ({ data-test-subj="aiopsSpikeAnalysisGroupsTableColumnGroupBadge" color="hollow" > - +{Object.keys(repeatedValues).length} more + +{Object.keys(repeatedValues).length}{' '} + @@ -169,15 +279,141 @@ export const SpikeAnalysisGroupsTable: FC = ({ }, sortable: false, textOnly: true, + valign: 'top', + }, + { + 'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnLogRate', + width: NARROW_COLUMN_WIDTH, + field: 'pValue', + name: ( + + <> + + + + + ), + render: (_, { histogram, id }) => ( + + ), + sortable: false, + valign: 'top', }, { 'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnDocCount', + width: NARROW_COLUMN_WIDTH, field: 'docCount', - name: i18n.translate('xpack.aiops.correlations.correlationsTable.docCountLabel', { + name: i18n.translate('xpack.aiops.correlations.spikeAnalysisTableGroups.docCountLabel', { defaultMessage: 'Doc count', }), sortable: true, - width: '20%', + valign: 'top', + }, + { + 'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnPValue', + width: NARROW_COLUMN_WIDTH, + field: 'pValue', + name: ( + + <> + + + + + ), + render: (pValue: number | null) => pValue?.toPrecision(3) ?? NOT_AVAILABLE, + sortable: true, + valign: 'top', + }, + { + 'data-test-subj': 'aiopsSpikeAnalysisTableColumnImpact', + width: NARROW_COLUMN_WIDTH, + field: 'pValue', + name: ( + + <> + + + + + ), + render: (_, { pValue }) => { + if (!pValue) return NOT_AVAILABLE; + const label = getFailedTransactionsCorrelationImpactLabel(pValue); + return label ? {label.impact} : null; + }, + sortable: true, + valign: 'top', + }, + { + 'data-test-subj': 'aiOpsSpikeAnalysisTableColumnAction', + name: i18n.translate('xpack.aiops.spikeAnalysisTable.actionsColumnName', { + defaultMessage: 'Actions', + }), + actions: [ + { + name: () => ( + + + + ), + description: viewInDiscoverMessage, + type: 'button', + onClick: async (tableItem) => { + const openInDiscoverUrl = await generateDiscoverUrl(tableItem); + if (typeof openInDiscoverUrl === 'string') { + await application.navigateToUrl(openInDiscoverUrl); + } + }, + enabled: () => discoverUrlError === undefined, + }, + ], + width: ACTIONS_COLUMN_WIDTH, + valign: 'top', }, ]; @@ -228,6 +464,7 @@ export const SpikeAnalysisGroupsTable: FC = ({ compressed columns={columns} items={pageOfItems} + itemId="id" itemIdToExpandedRowMap={itemIdToExpandedRowMap} onChange={onChange} pagination={pagination} @@ -236,6 +473,16 @@ export const SpikeAnalysisGroupsTable: FC = ({ rowProps={(group) => { return { 'data-test-subj': `aiopsSpikeAnalysisGroupsTableRow row-${group.id}`, + onMouseEnter: () => { + if (onSelectedGroup) { + onSelectedGroup(group); + } + }, + onMouseLeave: () => { + if (onSelectedGroup) { + onSelectedGroup(null); + } + }, }; }} /> diff --git a/x-pack/plugins/aiops/public/get_document_stats.ts b/x-pack/plugins/aiops/public/get_document_stats.ts index 1df4e4bd57ae8..07324b5f10605 100644 --- a/x-pack/plugins/aiops/public/get_document_stats.ts +++ b/x-pack/plugins/aiops/public/get_document_stats.ts @@ -14,6 +14,7 @@ import type { ChangePoint } from '@kbn/ml-agg-utils'; import type { Query } from '@kbn/es-query'; import { buildBaseFilterCriteria } from './application/utils/query_utils'; +import { GroupTableItem } from './components/spike_analysis_table/spike_analysis_table_groups'; export interface DocumentCountStats { interval?: number; @@ -34,6 +35,7 @@ export interface DocumentStatsSearchStrategyParams { fieldsToFetch?: string[]; selectedChangePoint?: ChangePoint; includeSelectedChangePoint?: boolean; + selectedGroup?: GroupTableItem | null; } export const getDocumentCountStatsRequest = (params: DocumentStatsSearchStrategyParams) => { @@ -48,6 +50,7 @@ export const getDocumentCountStatsRequest = (params: DocumentStatsSearchStrategy fieldsToFetch, selectedChangePoint, includeSelectedChangePoint, + selectedGroup, } = params; const size = 0; @@ -57,7 +60,8 @@ export const getDocumentCountStatsRequest = (params: DocumentStatsSearchStrategy latestMs, searchQuery, selectedChangePoint, - includeSelectedChangePoint + includeSelectedChangePoint, + selectedGroup ); // Don't use the sampler aggregation as this can lead to some potentially diff --git a/x-pack/plugins/aiops/public/hooks/use_data.ts b/x-pack/plugins/aiops/public/hooks/use_data.ts index 9ea8f9bd2335b..05736fe00e4fc 100644 --- a/x-pack/plugins/aiops/public/hooks/use_data.ts +++ b/x-pack/plugins/aiops/public/hooks/use_data.ts @@ -28,6 +28,7 @@ import { import { useTimefilter } from './use_time_filter'; import { useDocumentCountStats } from './use_document_count_stats'; import type { Dictionary } from './use_url_state'; +import type { GroupTableItem } from '../components/spike_analysis_table/spike_analysis_table_groups'; const DEFAULT_BAR_TARGET = 75; @@ -39,7 +40,8 @@ export const useData = ( aiopsListState: AiOpsIndexBasedAppState, onUpdate: (params: Dictionary) => void, selectedChangePoint?: ChangePoint, - barTarget: number = DEFAULT_BAR_TARGET + barTarget: number = DEFAULT_BAR_TARGET, + selectedGroup?: GroupTableItem | null ) => { const { uiSettings, @@ -109,15 +111,25 @@ export const useData = ( const overallStatsRequest = useMemo(() => { return fieldStatsRequest - ? { ...fieldStatsRequest, selectedChangePoint, includeSelectedChangePoint: false } + ? { + ...fieldStatsRequest, + selectedChangePoint, + selectedGroup, + includeSelectedChangePoint: false, + } : undefined; - }, [fieldStatsRequest, selectedChangePoint]); + }, [fieldStatsRequest, selectedChangePoint, selectedGroup]); const selectedChangePointStatsRequest = useMemo(() => { - return fieldStatsRequest && selectedChangePoint - ? { ...fieldStatsRequest, selectedChangePoint, includeSelectedChangePoint: true } + return fieldStatsRequest && (selectedChangePoint || selectedGroup) + ? { + ...fieldStatsRequest, + selectedChangePoint, + selectedGroup, + includeSelectedChangePoint: true, + } : undefined; - }, [fieldStatsRequest, selectedChangePoint]); + }, [fieldStatsRequest, selectedChangePoint, selectedGroup]); const documentStats = useDocumentCountStats( overallStatsRequest, diff --git a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts index f0fadf9476e74..48ea2dbddb1c3 100644 --- a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts +++ b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts @@ -18,10 +18,12 @@ import type { DataRequestHandlerContext } from '@kbn/data-plugin/server'; import { streamFactory } from '@kbn/aiops-utils'; import type { ChangePoint, NumericChartData, NumericHistogramField } from '@kbn/ml-agg-utils'; import { fetchHistogramsForFields } from '@kbn/ml-agg-utils'; +import { stringHash } from '@kbn/ml-string-hash'; import { addChangePointsAction, addChangePointsGroupAction, + addChangePointsGroupHistogramAction, addChangePointsHistogramAction, aiopsExplainLogRateSpikesSchema, addErrorAction, @@ -35,8 +37,14 @@ import type { AiopsLicense } from '../types'; import { fetchChangePointPValues } from './queries/fetch_change_point_p_values'; import { fetchFieldCandidates } from './queries/fetch_field_candidates'; -import { fetchFrequentItems } from './queries/fetch_frequent_items'; import { + dropDuplicates, + fetchFrequentItems, + groupDuplicates, +} from './queries/fetch_frequent_items'; +import type { ItemsetResult } from './queries/fetch_frequent_items'; +import { + getFieldValuePairCounts, getSimpleHierarchicalTree, getSimpleHierarchicalTreeLeaves, markDuplicates, @@ -210,48 +218,232 @@ export const defineExplainLogRateSpikesRoute = ( return; } + const histogramFields: [NumericHistogramField] = [ + { fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE }, + ]; + + const [overallTimeSeries] = (await fetchHistogramsForFields( + client, + request.body.index, + { match_all: {} }, + // fields + histogramFields, + // samplerShardSize + -1, + undefined + )) as [NumericChartData]; + if (groupingEnabled) { + // To optimize the `frequent_items` query, we identify duplicate change points by count attributes. + // Note this is a compromise and not 100% accurate because there could be change points that + // have the exact same counts but still don't co-occur. + const duplicateIdentifier: Array = [ + 'doc_count', + 'bg_count', + 'total_doc_count', + 'total_bg_count', + ]; + + // These are the deduplicated change points we pass to the `frequent_items` aggregation. + const deduplicatedChangePoints = dropDuplicates(changePoints, duplicateIdentifier); + + // We use the grouped change points to later repopulate + // the `frequent_items` result with the missing duplicates. + const groupedChangePoints = groupDuplicates(changePoints, duplicateIdentifier).filter( + (g) => g.group.length > 1 + ); + const { fields, df } = await fetchFrequentItems( client, request.body.index, JSON.parse(request.body.searchQuery) as estypes.QueryDslQueryContainer, - changePoints, + deduplicatedChangePoints, request.body.timeFieldName, request.body.deviationMin, request.body.deviationMax ); - // Filter itemsets by significant change point field value pairs - const filteredDf = df.filter((fi) => { - const { set: currentItems } = fi; + // The way the `frequent_items` aggregations works could return item sets that include + // field/value pairs that are not part of the original list of significant change points. + // This cleans up groups and removes those unrelated field/value pairs. + const filteredDf = df + .map((fi) => { + fi.set = Object.entries(fi.set).reduce( + (set, [field, value]) => { + if ( + changePoints.some((cp) => cp.fieldName === field && cp.fieldValue === value) + ) { + set[field] = value; + } + return set; + }, + {} + ); + fi.size = Object.keys(fi.set).length; + return fi; + }) + .filter((fi) => fi.size > 1); + + // `frequent_items` returns lot of different small groups of field/value pairs that co-occur. + // The following steps analyse these small groups, identify overlap between these groups, + // and then summarize them in larger groups where possible. + + // Get a tree structure based on `frequent_items`. + const { root } = getSimpleHierarchicalTree(filteredDf, true, false, fields); + + // Each leave of the tree will be a summarized group of co-occuring field/value pairs. + const treeLeaves = getSimpleHierarchicalTreeLeaves(root, []); + + // To be able to display a more cleaned up results table in the UI, we identify field/value pairs + // that occur in multiple groups. This will allow us to highlight field/value pairs that are + // unique to a group in a better way. This step will also re-add duplicates we identified in the + // beginning and didn't pass on to the `frequent_items` agg. + const fieldValuePairCounts = getFieldValuePairCounts(treeLeaves); + const changePointGroups = markDuplicates(treeLeaves, fieldValuePairCounts).map((g) => { + const group = [...g.group]; + + for (const groupItem of g.group) { + const { duplicate } = groupItem; + const duplicates = groupedChangePoints.find((d) => + d.group.some( + (dg) => + dg.fieldName === groupItem.fieldName && dg.fieldValue === groupItem.fieldValue + ) + ); - return Object.entries(currentItems).every(([key, value]) => { - return changePoints.some((cp) => { - return cp.fieldName === key && cp.fieldValue === value; - }); + if (duplicates !== undefined) { + group.push( + ...duplicates.group.map((d) => { + return { + fieldName: d.fieldName, + fieldValue: d.fieldValue, + duplicate, + }; + }) + ); + } + } + + return { + ...g, + group, + }; + }); + + // Some field/value pairs might not be part of the `frequent_items` result set, for example + // because they don't co-occur with other field/value pairs or because of the limits we set on the query. + // In this next part we identify those missing pairs and add them as individual groups. + const missingChangePoints = deduplicatedChangePoints.filter((cp) => { + return !changePointGroups.some((cpg) => { + return cpg.group.some( + (d) => d.fieldName === cp.fieldName && d.fieldValue === cp.fieldValue + ); }); }); - const { root } = getSimpleHierarchicalTree(filteredDf, true, false, fields); - const changePointsGroups = getSimpleHierarchicalTreeLeaves(root, []); + changePointGroups.push( + ...missingChangePoints.map(({ fieldName, fieldValue, doc_count: docCount, pValue }) => { + const duplicates = groupedChangePoints.find((d) => + d.group.some((dg) => dg.fieldName === fieldName && dg.fieldValue === fieldValue) + ); + if (duplicates !== undefined) { + return { + id: `${stringHash( + JSON.stringify( + duplicates.group.map((d) => ({ + fieldName: d.fieldName, + fieldValue: d.fieldValue, + })) + ) + )}`, + group: duplicates.group.map((d) => ({ + fieldName: d.fieldName, + fieldValue: d.fieldValue, + duplicate: false, + })), + docCount, + pValue, + }; + } else { + return { + id: `${stringHash(JSON.stringify({ fieldName, fieldValue }))}`, + group: [ + { + fieldName, + fieldValue, + duplicate: false, + }, + ], + docCount, + pValue, + }; + } + }) + ); - push(addChangePointsGroupAction(markDuplicates(changePointsGroups))); - } + // Finally, we'll find out if there's at least one group with at least two items, + // only then will we return the groups to the clients and make the grouping option available. + const maxItems = Math.max(...changePointGroups.map((g) => g.group.length)); - const histogramFields: [NumericHistogramField] = [ - { fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE }, - ]; + if (maxItems > 1) { + push(addChangePointsGroupAction(changePointGroups)); + } - const [overallTimeSeries] = (await fetchHistogramsForFields( - client, - request.body.index, - { match_all: {} }, - // fields - histogramFields, - // samplerShardSize - -1, - undefined - )) as [NumericChartData]; + if (changePointGroups) { + await asyncForEach(changePointGroups, async (cpg, index) => { + const histogramQuery = { + bool: { + filter: cpg.group.map((d) => ({ + term: { [d.fieldName]: d.fieldValue }, + })), + }, + }; + + const [cpgTimeSeries] = (await fetchHistogramsForFields( + client, + request.body.index, + histogramQuery, + // fields + [ + { + fieldName: request.body.timeFieldName, + type: KBN_FIELD_TYPES.DATE, + interval: overallTimeSeries.interval, + min: overallTimeSeries.stats[0], + max: overallTimeSeries.stats[1], + }, + ], + // samplerShardSize + -1, + undefined + )) as [NumericChartData]; + + const histogram = + overallTimeSeries.data.map((o, i) => { + const current = cpgTimeSeries.data.find( + (d1) => d1.key_as_string === o.key_as_string + ) ?? { + doc_count: 0, + }; + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_change_point: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + }) ?? []; + + push( + addChangePointsGroupHistogramAction([ + { + id: cpg.id, + histogram, + }, + ]) + ); + }); + } + } // time series filtered by fields if (changePoints) { diff --git a/x-pack/plugins/aiops/server/routes/queries/fetch_frequent_items.ts b/x-pack/plugins/aiops/server/routes/queries/fetch_frequent_items.ts index 02d20ba18795c..055c22397064f 100644 --- a/x-pack/plugins/aiops/server/routes/queries/fetch_frequent_items.ts +++ b/x-pack/plugins/aiops/server/routes/queries/fetch_frequent_items.ts @@ -10,7 +10,7 @@ import { uniq, uniqWith, pick, isEqual } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import type { ChangePoint } from '@kbn/ml-agg-utils'; +import type { ChangePoint, FieldValuePair } from '@kbn/ml-agg-utils'; interface FrequentItemsAggregation extends estypes.AggregationsSamplerAggregation { fi: { @@ -18,8 +18,32 @@ interface FrequentItemsAggregation extends estypes.AggregationsSamplerAggregatio }; } -function dropDuplicates(cp: ChangePoint[], uniqueFields: string[]) { - return uniqWith(cp, (a, b) => isEqual(pick(a, uniqueFields), pick(b, uniqueFields))); +export function dropDuplicates(cps: ChangePoint[], uniqueFields: Array) { + return uniqWith(cps, (a, b) => isEqual(pick(a, uniqueFields), pick(b, uniqueFields))); +} + +interface ChangePointDuplicateGroup { + keys: Pick; + group: ChangePoint[]; +} +export function groupDuplicates(cps: ChangePoint[], uniqueFields: Array) { + const groups: ChangePointDuplicateGroup[] = []; + + for (const cp of cps) { + const compareAttributes = pick(cp, uniqueFields); + + const groupIndex = groups.findIndex((g) => isEqual(g.keys, compareAttributes)); + if (groupIndex === -1) { + groups.push({ + keys: compareAttributes, + group: [cp], + }); + } else { + groups[groupIndex].group.push(cp); + } + } + + return groups; } export async function fetchFrequentItems( @@ -31,17 +55,8 @@ export async function fetchFrequentItems( deviationMin: number, deviationMax: number ) { - // first remove duplicates in sig terms - note this is not strictly perfect as there could - // be conincidentally equal counts, but in general is ok... - const terms = dropDuplicates(changePoints, [ - 'doc_count', - 'bg_count', - 'total_doc_count', - 'total_bg_count', - ]); - // get unique fields that are left - const fields = [...new Set(terms.map((t) => t.fieldName))]; + const fields = [...new Set(changePoints.map((t) => t.fieldName))]; // TODO add query params const query = { @@ -58,7 +73,7 @@ export async function fetchFrequentItems( }, }, ], - should: terms.map((t) => { + should: changePoints.map((t) => { return { term: { [t.fieldName]: t.fieldValue } }; }), }, @@ -68,7 +83,7 @@ export async function fetchFrequentItems( field, })); - const totalDocCount = terms[0].total_doc_count; + const totalDocCount = changePoints[0].total_doc_count; const minDocCount = 50000; let sampleProbability = 1; @@ -88,7 +103,7 @@ export async function fetchFrequentItems( frequent_items: { minimum_set_size: 2, size: 200, - minimum_support: 0.1, + minimum_support: 0.01, fields: aggFields, }, }, @@ -153,7 +168,7 @@ export async function fetchFrequentItems( return; } - result.size = Object.keys(result).length; + result.size = Object.keys(result.set).length; result.maxPValue = maxPValue; result.doc_count = fis.doc_count; result.support = fis.support; @@ -162,15 +177,21 @@ export async function fetchFrequentItems( results.push(result); }); + results.sort((a, b) => { + return b.doc_count - a.doc_count; + }); + + const uniqueFields = uniq(results.flatMap((r) => Object.keys(r.set))); + return { - fields: uniq(results.flatMap((r) => Object.keys(r.set))), + fields: uniqueFields, df: results, totalDocCount: totalDocCountFi, }; } export interface ItemsetResult { - set: Record; + set: Record; size: number; maxPValue: number; doc_count: number; diff --git a/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.test.ts b/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.test.ts new file mode 100644 index 0000000000000..5f2125a583db7 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.test.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ChangePointGroup } from '@kbn/ml-agg-utils'; + +import { getFieldValuePairCounts, markDuplicates } from './get_simple_hierarchical_tree'; + +const changePointGroups: ChangePointGroup[] = [ + { + id: 'group-1', + group: [ + { + fieldName: 'custom_field.keyword', + fieldValue: 'deviation', + }, + { + fieldName: 'airline', + fieldValue: 'UAL', + }, + ], + docCount: 101, + pValue: 0.01, + }, + { + id: 'group-2', + group: [ + { + fieldName: 'custom_field.keyword', + fieldValue: 'deviation', + }, + { + fieldName: 'airline', + fieldValue: 'AAL', + }, + ], + docCount: 49, + pValue: 0.001, + }, +]; + +describe('get_simple_hierarchical_tree', () => { + describe('getFieldValuePairCounts', () => { + it('returns a nested record with field/value pair counts', () => { + const fieldValuePairCounts = getFieldValuePairCounts(changePointGroups); + + expect(fieldValuePairCounts).toEqual({ + airline: { + AAL: 1, + UAL: 1, + }, + 'custom_field.keyword': { + deviation: 2, + }, + }); + }); + }); + + describe('markDuplicates', () => { + it('marks duplicates based on change point groups', () => { + const fieldValuePairCounts = getFieldValuePairCounts(changePointGroups); + const markedDuplicates = markDuplicates(changePointGroups, fieldValuePairCounts); + + expect(markedDuplicates).toEqual([ + { + id: 'group-1', + group: [ + { + fieldName: 'custom_field.keyword', + fieldValue: 'deviation', + duplicate: true, + }, + { + fieldName: 'airline', + fieldValue: 'UAL', + duplicate: false, + }, + ], + docCount: 101, + pValue: 0.01, + }, + { + id: 'group-2', + group: [ + { + fieldName: 'custom_field.keyword', + fieldValue: 'deviation', + duplicate: true, + }, + { + fieldName: 'airline', + fieldValue: 'AAL', + duplicate: false, + }, + ], + docCount: 49, + pValue: 0.001, + }, + ]); + }); + }); +}); diff --git a/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.ts b/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.ts index 7d00cc4fc3e0f..9f39d1eb11f68 100644 --- a/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.ts +++ b/x-pack/plugins/aiops/server/routes/queries/get_simple_hierarchical_tree.ts @@ -8,17 +8,18 @@ // import { omit, uniq } from 'lodash'; import type { ChangePointGroup, FieldValuePair } from '@kbn/ml-agg-utils'; +import { stringHash } from '@kbn/ml-string-hash'; import type { ItemsetResult } from './fetch_frequent_items'; function getValueCounts(df: ItemsetResult[], field: string) { - return df.reduce((p, c) => { + return df.reduce>((p, c) => { if (c.set[field] === undefined) { return p; } p[c.set[field]] = p[c.set[field]] ? p[c.set[field]] + 1 : 1; return p; - }, {} as Record); + }, {}); } function getValuesDescending(df: ItemsetResult[], field: string): string[] { @@ -34,6 +35,7 @@ interface NewNode { name: string; set: FieldValuePair[]; docCount: number; + pValue: number | null; children: NewNode[]; icon: string; iconStyle: string; @@ -51,6 +53,7 @@ function NewNodeFactory(name: string): NewNode { name, set: [], docCount: 0, + pValue: 0, children, icon: 'default', iconStyle: 'default', @@ -87,8 +90,8 @@ function dfDepthFirstSearch( displayOther: boolean ) { const filteredItemSets = iss.filter((is) => { - for (const [key, values] of Object.entries(is.set)) { - if (key === field && values.includes(value)) { + for (const [key, setValue] of Object.entries(is.set)) { + if (key === field && setValue === value) { return true; } } @@ -100,6 +103,7 @@ function dfDepthFirstSearch( } const docCount = Math.max(...filteredItemSets.map((fis) => fis.doc_count)); + const pValue = Math.max(...filteredItemSets.map((fis) => fis.maxPValue)); const totalDocCount = Math.max(...filteredItemSets.map((fis) => fis.total_doc_count)); let label = `${parentLabel} ${value}`; @@ -110,6 +114,7 @@ function dfDepthFirstSearch( displayParent.name += ` ${value}`; displayParent.set.push({ fieldName: field, fieldValue: value }); displayParent.docCount = docCount; + displayParent.pValue = pValue; displayNode = displayParent; } else { displayNode = NewNodeFactory(`${docCount}/${totalDocCount}${label}`); @@ -117,6 +122,7 @@ function dfDepthFirstSearch( displayNode.set = [...displayParent.set]; displayNode.set.push({ fieldName: field, fieldValue: value }); displayNode.docCount = docCount; + displayNode.pValue = pValue; displayParent.addNode(displayNode); } @@ -144,6 +150,7 @@ function dfDepthFirstSearch( nextDisplayNode.iconStyle = 'warning'; nextDisplayNode.set = displayNode.set; nextDisplayNode.docCount = docCount; + nextDisplayNode.pValue = pValue; displayNode.addNode(nextDisplayNode); displayNode = nextDisplayNode; } @@ -224,9 +231,13 @@ export function getSimpleHierarchicalTreeLeaves( leaves: ChangePointGroup[], level = 1 ) { - // console.log(`${'-'.repeat(level)} ${tree.name} ${tree.children.length}`); if (tree.children.length === 0) { - leaves.push({ group: tree.set, docCount: tree.docCount }); + leaves.push({ + id: `${stringHash(JSON.stringify(tree.set))}`, + group: tree.set, + docCount: tree.docCount, + pValue: tree.pValue, + }); } else { for (const child of tree.children) { const newLeaves = getSimpleHierarchicalTreeLeaves(child, [], level + 1); @@ -236,29 +247,43 @@ export function getSimpleHierarchicalTreeLeaves( } } + if (leaves.length === 1 && leaves[0].group.length === 0 && leaves[0].docCount === 0) { + return []; + } + return leaves; } +type FieldValuePairCounts = Record>; /** - * Analyse duplicate field/value pairs in change point groups. + * Get a nested record of field/value pairs with counts */ -export function markDuplicates(cpgs: ChangePointGroup[]): ChangePointGroup[] { - const fieldValuePairCounts: Record = {}; - cpgs.forEach((cpg) => { - cpg.group.forEach((g) => { - const str = `${g.fieldName}$$$$${g.fieldValue}`; - fieldValuePairCounts[str] = fieldValuePairCounts[str] ? fieldValuePairCounts[str] + 1 : 1; +export function getFieldValuePairCounts(cpgs: ChangePointGroup[]): FieldValuePairCounts { + return cpgs.reduce((p, { group }) => { + group.forEach(({ fieldName, fieldValue }) => { + if (p[fieldName] === undefined) { + p[fieldName] = {}; + } + p[fieldName][fieldValue] = p[fieldName][fieldValue] ? p[fieldName][fieldValue] + 1 : 1; }); - }); + return p; + }, {}); +} +/** + * Analyse duplicate field/value pairs in change point groups. + */ +export function markDuplicates( + cpgs: ChangePointGroup[], + fieldValuePairCounts: FieldValuePairCounts +): ChangePointGroup[] { return cpgs.map((cpg) => { return { ...cpg, group: cpg.group.map((g) => { - const str = `${g.fieldName}$$$$${g.fieldValue}`; return { ...g, - duplicate: fieldValuePairCounts[str] > 1, + duplicate: fieldValuePairCounts[g.fieldName][g.fieldValue] > 1, }; }), }; diff --git a/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts b/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts index 6e6eb3cb43f0d..5efd2d7a49152 100644 --- a/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts +++ b/x-pack/plugins/alerting/server/usage/alerting_usage_collector.ts @@ -116,6 +116,13 @@ const byStatusSchema: MakeSchemaFrom['count_rules_by_execution_st warning: { type: 'long' }, }; +const byStatusPerDaySchema: MakeSchemaFrom['count_rules_by_execution_status_per_day'] = + { + success: { type: 'long' }, + failure: { type: 'long' }, + unknown: { type: 'long' }, + }; + const byNotifyWhenSchema: MakeSchemaFrom['count_rules_by_notify_when'] = { on_action_group_change: { type: 'long' }, on_active_alert: { type: 'long' }, @@ -200,6 +207,7 @@ export function createAlertingUsageCollector( count_rules_muted: 0, count_rules_with_muted_alerts: 0, count_connector_types_by_consumers: {}, + count_rules_by_execution_status_per_day: {}, avg_execution_time_per_day: 0, avg_execution_time_by_type_per_day: {}, avg_es_search_duration_per_day: 0, @@ -283,6 +291,7 @@ export function createAlertingUsageCollector( count_rules_muted: { type: 'long' }, count_rules_with_muted_alerts: { type: 'long' }, count_connector_types_by_consumers: { DYNAMIC_KEY: { DYNAMIC_KEY: { type: 'long' } } }, + count_rules_by_execution_status_per_day: byStatusPerDaySchema, avg_execution_time_per_day: { type: 'long' }, avg_execution_time_by_type_per_day: byTypeSchema, avg_es_search_duration_per_day: { type: 'long' }, diff --git a/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.test.ts b/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.test.ts index f3e21f6a161fa..64bc0ae8be0fb 100644 --- a/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.test.ts +++ b/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.test.ts @@ -1291,6 +1291,14 @@ describe('event log telemetry', () => { avg_total_search_duration: { value: 28.630434782608695, }, + by_execution_status: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'success', doc_count: 21 }, + { key: 'failure', doc_count: 22 }, + ], + }, }, }); @@ -1377,7 +1385,6 @@ describe('event log telemetry', () => { logs__alert__document__count: 0, }, }, - alertsPercentilesByType: { p50: { '__index-threshold': 1, @@ -1398,6 +1405,10 @@ describe('event log telemetry', () => { logs__alert__document__count: 0, }, }, + countRulesByExecutionStatus: { + failure: 22, + success: 21, + }, hasErrors: false, }); }); @@ -1437,6 +1448,7 @@ describe('event log telemetry', () => { generatedActionsPercentilesByType: {}, alertsPercentiles: {}, alertsPercentilesByType: {}, + countRulesByExecutionStatus: {}, }); }); }); diff --git a/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.ts b/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.ts index 703d579e66c25..e21df2376f4f8 100644 --- a/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.ts +++ b/x-pack/plugins/alerting/server/usage/lib/get_telemetry_from_event_log.ts @@ -54,15 +54,14 @@ interface GetExecutionsPerDayCountResults { generatedActionsPercentilesByType: Record>; alertsPercentiles: Record; alertsPercentilesByType: Record>; + countRulesByExecutionStatus: Record; } - interface GetExecutionTimeoutsPerDayCountResults { hasErrors: boolean; errorMessage?: string; countExecutionTimeouts: number; countExecutionTimeoutsByType: Record; } - interface GetExecutionCountsExecutionFailures extends AggregationsSingleBucketAggregateBase { by_reason: AggregationsTermsAggregateBase; } @@ -145,6 +144,11 @@ export async function getExecutionsPerDayCount({ }, aggs: eventLogAggs, }, + by_execution_status: { + terms: { + field: 'event.outcome', + }, + }, }, }, }; @@ -165,6 +169,7 @@ export async function getExecutionsPerDayCount({ avg_execution_time: AggregationsSingleMetricAggregateBase; avg_es_search_duration: AggregationsSingleMetricAggregateBase; avg_total_search_duration: AggregationsSingleMetricAggregateBase; + by_execution_status: AggregationsTermsAggregateBase; }; const aggregationsByRuleTypeId: AggregationsBuckets = @@ -176,6 +181,9 @@ export async function getExecutionsPerDayCount({ ...parseExecutionFailureByRuleType(aggregationsByRuleTypeId), ...parseExecutionCountAggregationResults(aggregations), countTotalRuleExecutions: totalRuleExecutions ?? 0, + countRulesByExecutionStatus: parseSimpleRuleTypeBucket( + aggregations.by_execution_status.buckets + ), }; } catch (err) { const errorMessage = err && err.message ? err.message : err.toString(); @@ -204,6 +212,7 @@ export async function getExecutionsPerDayCount({ generatedActionsPercentilesByType: {}, alertsPercentiles: {}, alertsPercentilesByType: {}, + countRulesByExecutionStatus: {}, }; } } @@ -313,6 +322,14 @@ export async function getExecutionTimeoutsPerDayCount({ * avg_total_search_duration: { // average total search duration across executions * value: 43.74647887323944, * }, + * by_execution_status: { + * "doc_count_error_upper_bound":0, + * "sum_other_doc_count":0, + * "buckets":[ + * {"key":"success","doc_count":48}, + * {"key":"failure","doc_count":1} + * ] + * } * } */ diff --git a/x-pack/plugins/alerting/server/usage/task.ts b/x-pack/plugins/alerting/server/usage/task.ts index 4f835f3c4a64f..ab20844948011 100644 --- a/x-pack/plugins/alerting/server/usage/task.ts +++ b/x-pack/plugins/alerting/server/usage/task.ts @@ -161,6 +161,8 @@ export function telemetryTaskRunner( dailyExecutionCounts.countFailedExecutionsByReason, count_rules_executions_failured_by_reason_by_type_per_day: dailyExecutionCounts.countFailedExecutionsByReasonByType, + count_rules_by_execution_status_per_day: + dailyExecutionCounts.countRulesByExecutionStatus, count_rules_executions_timeouts_per_day: dailyExecutionTimeoutCounts.countExecutionTimeouts, count_rules_executions_timeouts_by_type_per_day: diff --git a/x-pack/plugins/alerting/server/usage/types.ts b/x-pack/plugins/alerting/server/usage/types.ts index 29a32de29bc1a..15c0f0a962710 100644 --- a/x-pack/plugins/alerting/server/usage/types.ts +++ b/x-pack/plugins/alerting/server/usage/types.ts @@ -42,6 +42,7 @@ export interface AlertingUsage { count_rules_snoozed: number; count_rules_muted: number; count_rules_with_muted_alerts: number; + count_rules_by_execution_status_per_day: Record; percentile_num_generated_actions_per_day: { p50: number; p90: number; diff --git a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap index 3ac48a1e367ce..95c36d24aad5b 100644 --- a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap @@ -221,6 +221,10 @@ exports[`Error TRANSACTION_DURATION 1`] = `undefined`; exports[`Error TRANSACTION_DURATION_HISTOGRAM 1`] = `undefined`; +exports[`Error TRANSACTION_DURATION_SUMMARY 1`] = `undefined`; + +exports[`Error TRANSACTION_FAILURE_COUNT 1`] = `undefined`; + exports[`Error TRANSACTION_ID 1`] = `"transaction id"`; exports[`Error TRANSACTION_NAME 1`] = `undefined`; @@ -233,6 +237,8 @@ exports[`Error TRANSACTION_ROOT 1`] = `undefined`; exports[`Error TRANSACTION_SAMPLED 1`] = `undefined`; +exports[`Error TRANSACTION_SUCCESS_COUNT 1`] = `undefined`; + exports[`Error TRANSACTION_TYPE 1`] = `"request"`; exports[`Error TRANSACTION_URL 1`] = `undefined`; @@ -462,6 +468,10 @@ exports[`Span TRANSACTION_DURATION 1`] = `undefined`; exports[`Span TRANSACTION_DURATION_HISTOGRAM 1`] = `undefined`; +exports[`Span TRANSACTION_DURATION_SUMMARY 1`] = `undefined`; + +exports[`Span TRANSACTION_FAILURE_COUNT 1`] = `undefined`; + exports[`Span TRANSACTION_ID 1`] = `"transaction id"`; exports[`Span TRANSACTION_NAME 1`] = `undefined`; @@ -474,6 +484,8 @@ exports[`Span TRANSACTION_ROOT 1`] = `undefined`; exports[`Span TRANSACTION_SAMPLED 1`] = `undefined`; +exports[`Span TRANSACTION_SUCCESS_COUNT 1`] = `undefined`; + exports[`Span TRANSACTION_TYPE 1`] = `undefined`; exports[`Span TRANSACTION_URL 1`] = `undefined`; @@ -721,6 +733,10 @@ exports[`Transaction TRANSACTION_DURATION 1`] = `1337`; exports[`Transaction TRANSACTION_DURATION_HISTOGRAM 1`] = `undefined`; +exports[`Transaction TRANSACTION_DURATION_SUMMARY 1`] = `undefined`; + +exports[`Transaction TRANSACTION_FAILURE_COUNT 1`] = `undefined`; + exports[`Transaction TRANSACTION_ID 1`] = `"transaction id"`; exports[`Transaction TRANSACTION_NAME 1`] = `"transaction name"`; @@ -733,6 +749,8 @@ exports[`Transaction TRANSACTION_ROOT 1`] = `undefined`; exports[`Transaction TRANSACTION_SAMPLED 1`] = `true`; +exports[`Transaction TRANSACTION_SUCCESS_COUNT 1`] = `undefined`; + exports[`Transaction TRANSACTION_TYPE 1`] = `"transaction type"`; exports[`Transaction TRANSACTION_URL 1`] = `"http://www.elastic.co"`; diff --git a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts index 575588018b369..f29bf3c607e86 100644 --- a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts +++ b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts @@ -46,12 +46,15 @@ export const PROCESSOR_EVENT = 'processor.event'; export const TRANSACTION_DURATION = 'transaction.duration.us'; export const TRANSACTION_DURATION_HISTOGRAM = 'transaction.duration.histogram'; +export const TRANSACTION_DURATION_SUMMARY = 'transaction.duration.summary'; export const TRANSACTION_TYPE = 'transaction.type'; export const TRANSACTION_RESULT = 'transaction.result'; export const TRANSACTION_NAME = 'transaction.name'; export const TRANSACTION_ID = 'transaction.id'; export const TRANSACTION_SAMPLED = 'transaction.sampled'; export const TRANSACTION_PAGE_URL = 'transaction.page.url'; +export const TRANSACTION_FAILURE_COUNT = 'transaction.failure_count'; +export const TRANSACTION_SUCCESS_COUNT = 'transaction.success_count'; // for transaction metrics export const TRANSACTION_ROOT = 'transaction.root'; diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/setting_form_row.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/setting_form_row.tsx index ccc483182d772..37bf55ec1f456 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/setting_form_row.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/setting_form_row.tsx @@ -18,6 +18,7 @@ import { EuiIconTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { EuiMarkdownFormat } from '@elastic/eui'; import { SettingDefinition } from '../../../../../../../common/agent_configuration/setting_definitions/types'; import { validateSetting } from '../../../../../../../common/agent_configuration/setting_definitions'; import { @@ -163,7 +164,7 @@ export function SettingFormRow({ } description={ <> - {setting.description} + {setting.description} {setting.defaultValue && ( <> diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/settings_page.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/settings_page.tsx index f4e8f52cdc1df..94357cf4fb63f 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/settings_page.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_configurations/agent_configuration_create_edit/settings_page/settings_page.tsx @@ -6,24 +6,20 @@ */ import { - EuiBottomBar, EuiButton, - EuiButtonEmpty, EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiForm, - EuiHealth, + EuiHorizontalRule, EuiLoadingSpinner, EuiSpacer, EuiStat, - EuiText, - EuiHorizontalRule, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { useUiTracker } from '@kbn/observability-plugin/public'; import React, { useMemo, useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { useUiTracker } from '@kbn/observability-plugin/public'; import { getOptionLabel } from '../../../../../../../common/agent_configuration/all_option'; import { AgentConfigurationIntake } from '../../../../../../../common/agent_configuration/configuration_types'; import { @@ -34,6 +30,7 @@ import { import { AgentName } from '../../../../../../../typings/es_schemas/ui/fields/agent'; import { useApmPluginContext } from '../../../../../../context/apm_plugin/use_apm_plugin_context'; import { FETCH_STATUS } from '../../../../../../hooks/use_fetcher'; +import { BottomBarActions } from '../../../bottom_bar_actions'; import { saveConfig } from './save_config'; import { SettingFormRow } from './setting_form_row'; @@ -190,53 +187,16 @@ export function SettingsPage({ {/* Bottom bar with save button */} {unsavedChangesCount > 0 && ( - - - - - - {i18n.translate('xpack.apm.unsavedChanges', { - defaultMessage: - '{unsavedChangesCount, plural, =0{0 unsaved changes} one {1 unsaved change} other {# unsaved changes}} ', - values: { unsavedChangesCount }, - })} - - - - - - - {i18n.translate( - 'xpack.apm.agentConfig.settingsPage.discardChangesButton', - { defaultMessage: 'Discard changes' } - )} - - - - - {i18n.translate( - 'xpack.apm.agentConfig.settingsPage.saveButton', - { defaultMessage: 'Save configuration' } - )} - - - - - - + )} ); diff --git a/x-pack/plugins/apm/public/components/app/settings/bottom_bar_actions/index.tsx b/x-pack/plugins/apm/public/components/app/settings/bottom_bar_actions/index.tsx new file mode 100644 index 0000000000000..85ee597b754ec --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/settings/bottom_bar_actions/index.tsx @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + EuiBottomBar, + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiHealth, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +interface Props { + unsavedChangesCount: number; + isLoading: boolean; + onDiscardChanges: () => void; + onSave: () => void; + saveLabel: string; +} + +export function BottomBarActions({ + isLoading, + onDiscardChanges, + onSave, + unsavedChangesCount, + saveLabel, +}: Props) { + return ( + + + + + + {i18n.translate('xpack.apm.bottomBarActions.unsavedChanges', { + defaultMessage: + '{unsavedChangesCount, plural, =0{0 unsaved changes} one {1 unsaved change} other {# unsaved changes}} ', + values: { unsavedChangesCount }, + })} + + + + + + + {i18n.translate( + 'xpack.apm.bottomBarActions.discardChangesButton', + { + defaultMessage: 'Discard changes', + } + )} + + + + + {saveLabel} + + + + + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx b/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx index ef41b75aedeaf..d8e62397626f8 100644 --- a/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { EuiButton } from '@elastic/eui'; import { LazyField } from '@kbn/advanced-settings-plugin/public'; import { i18n } from '@kbn/i18n'; import { @@ -20,6 +19,7 @@ import { isEmpty } from 'lodash'; import React from 'react'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { useApmEditableSettings } from '../../../../hooks/use_apm_editable_settings'; +import { BottomBarActions } from '../bottom_bar_actions'; const apmSettingsKeys = [ enableComparisonByDefault, @@ -38,6 +38,7 @@ export function GeneralSettings() { unsavedChanges, saveAll, isSaving, + cleanUnsavedChanges, } = useApmEditableSettings(apmSettingsKeys); async function handleSave() { @@ -76,16 +77,17 @@ export function GeneralSettings() { /> ); })} - - {i18n.translate('xpack.apm.labs.reload', { - defaultMessage: 'Reload to apply changes', - })} - + {!isEmpty(unsavedChanges) && ( + + )} ); } diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx index 9622acb525618..3f84a4bdb1347 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx @@ -14,10 +14,11 @@ import { import { i18n } from '@kbn/i18n'; import { omit } from 'lodash'; import React from 'react'; +import { enableAwsLambdaMetrics } from '@kbn/observability-plugin/common'; import { - isMobileAgentName, isJavaAgentName, isJRubyAgent, + isMobileAgentName, isRumAgentName, isServerlessAgent, } from '../../../../../common/agent_name'; @@ -29,13 +30,13 @@ import { ServiceAnomalyTimeseriesContextProvider } from '../../../../context/ser import { useApmParams } from '../../../../hooks/use_apm_params'; import { useApmRouter } from '../../../../hooks/use_apm_router'; import { useTimeRange } from '../../../../hooks/use_time_range'; +import { getAlertingCapabilities } from '../../../alerting/get_alerting_capabilities'; +import { BetaBadge } from '../../../shared/beta_badge'; import { SearchBar } from '../../../shared/search_bar'; import { ServiceIcons } from '../../../shared/service_icons'; +import { TechnicalPreviewBadge } from '../../../shared/technical_preview_badge'; import { ApmMainTemplate } from '../apm_main_template'; import { AnalyzeDataButton } from './analyze_data_button'; -import { getAlertingCapabilities } from '../../../alerting/get_alerting_capabilities'; -import { BetaBadge } from '../../../shared/beta_badge'; -import { TechnicalPreviewBadge } from '../../../shared/technical_preview_badge'; type Tab = NonNullable[0] & { key: @@ -139,17 +140,21 @@ function TemplateWithContext({ export function isMetricsTabHidden({ agentName, runtimeName, + isAwsLambdaEnabled, }: { agentName?: string; runtimeName?: string; + isAwsLambdaEnabled?: boolean; }) { + if (isServerlessAgent(runtimeName)) { + return !isAwsLambdaEnabled; + } return ( !agentName || isRumAgentName(agentName) || isJavaAgentName(agentName) || isMobileAgentName(agentName) || - isJRubyAgent(agentName, runtimeName) || - isServerlessAgent(runtimeName) + isJRubyAgent(agentName, runtimeName) ); } @@ -192,6 +197,11 @@ function useTabs({ selectedTab }: { selectedTab: Tab['key'] }) { const router = useApmRouter(); + const isAwsLambdaEnabled = core.uiSettings.get( + enableAwsLambdaMetrics, + true + ); + const { path: { serviceName }, query: queryFromUrl, @@ -257,7 +267,14 @@ function useTabs({ selectedTab }: { selectedTab: Tab['key'] }) { label: i18n.translate('xpack.apm.serviceDetails.metricsTabLabel', { defaultMessage: 'Metrics', }), - hidden: isMetricsTabHidden({ agentName, runtimeName }), + append: isServerlessAgent(runtimeName) ? ( + + ) : undefined, + hidden: isMetricsTabHidden({ + agentName, + runtimeName, + isAwsLambdaEnabled, + }), }, { key: 'nodes', diff --git a/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx index 1ad5227813d54..41ad3acda28a0 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiTitle } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiTitle } from '@elastic/eui'; import React from 'react'; import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; import { @@ -60,9 +60,22 @@ interface Props { export function MetricsChart({ chart, fetchStatus }: Props) { return ( <> - - {chart.title} - + + + + {chart.title} + + + {chart.description && ( + + + + )} + {allSeries.map((serie) => { - const Series = serie.type === 'area' ? AreaSeries : LineSeries; + const Series = getChartType(serie.type); return ( { + const commonProps = { + config, + apmEventClient, + kuery, + start, + end, + }; + const [searchAggregatedTransactions, searchAggregatedServiceMetrics] = + await Promise.all([ + getSearchAggregatedTransactions(commonProps), + getSearchAggregatedServiceMetrics(commonProps), + ]); + + return { + searchAggregatedTransactions, + searchAggregatedServiceMetrics, + }; +} diff --git a/x-pack/plugins/apm/server/lib/helpers/service_metrics/get_has_aggregated_service_metrics.test.ts b/x-pack/plugins/apm/server/lib/helpers/service_metrics/get_has_aggregated_service_metrics.test.ts new file mode 100644 index 0000000000000..d78190d56e20a --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/service_metrics/get_has_aggregated_service_metrics.test.ts @@ -0,0 +1,124 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getSearchAggregatedServiceMetrics } from '.'; +import { + SearchParamsMock, + inspectSearchParams, +} from '../../../utils/test_helpers'; +import { Setup } from '../setup_request'; + +const mockResponseWithServiceMetricsHits = { + took: 398, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 1, + relation: 'gte' as const, + }, + hits: [], + }, +}; + +const mockResponseWithServiceMetricsNoHits = { + took: 398, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 0, + relation: 'gte' as const, + }, + hits: [], + }, +}; + +describe('get default configuration for aggregated service metrics', () => { + it('should be false by default', async () => { + const mockSetup = { + apmEventClient: { search: () => Promise.resolve(response) }, + config: {}, + } as unknown as Setup; + + const response = await getSearchAggregatedServiceMetrics({ + apmEventClient: mockSetup.apmEventClient, + config: mockSetup.config, + kuery: '', + }); + expect(response).toBeFalsy(); + }); +}); + +describe('get has aggregated', () => { + it('should be false when xpack.apm.searchAggregatedServiceMetrics=false ', async () => { + const mockSetup = { + apmEventClient: { search: () => Promise.resolve(response) }, + config: { 'xpack.apm.searchAggregatedServiceMetrics': false }, + } as unknown as Setup; + + const response = await getSearchAggregatedServiceMetrics({ + apmEventClient: mockSetup.apmEventClient, + config: mockSetup.config, + kuery: '', + }); + expect(response).toBeFalsy(); + }); + + describe('with xpack.apm.searchAggregatedServiceMetrics=true', () => { + let mock: SearchParamsMock; + + const config = { + searchAggregatedServiceMetrics: true, + }; + + afterEach(() => { + mock.teardown(); + }); + it('should be true when service metrics data are found', async () => { + mock = await inspectSearchParams( + (setup) => + getSearchAggregatedServiceMetrics({ + apmEventClient: setup.apmEventClient, + config: setup.config, + kuery: '', + }), + { + config, + mockResponse: () => mockResponseWithServiceMetricsHits, + } + ); + expect(mock.response).toBeTruthy(); + }); + + it('should be false when service metrics data are not found', async () => { + mock = await inspectSearchParams( + (setup) => + getSearchAggregatedServiceMetrics({ + apmEventClient: setup.apmEventClient, + config: setup.config, + kuery: '', + }), + { + config, + mockResponse: () => mockResponseWithServiceMetricsNoHits, + } + ); + expect(mock.response).toBeFalsy(); + }); + }); +}); diff --git a/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts b/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts new file mode 100644 index 0000000000000..fd449734e9772 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { METRICSET_NAME } from '../../../../common/elasticsearch_fieldnames'; +import { APMConfig } from '../../..'; +import { APMEventClient } from '../create_es_client/create_apm_event_client'; + +export async function getSearchAggregatedServiceMetrics({ + config, + start, + end, + apmEventClient, + kuery, +}: { + config: APMConfig; + start?: number; + end?: number; + apmEventClient: APMEventClient; + kuery: string; +}): Promise { + if (config.searchAggregatedServiceMetrics) { + return getHasAggregatedServicesMetrics({ + start, + end, + apmEventClient, + kuery, + }); + } + + return false; +} + +export async function getHasAggregatedServicesMetrics({ + start, + end, + apmEventClient, + kuery, +}: { + start?: number; + end?: number; + apmEventClient: APMEventClient; + kuery: string; +}) { + const response = await apmEventClient.search( + 'get_has_aggregated_service_metrics', + { + apm: { + events: [ProcessorEvent.metric], + }, + body: { + size: 1, + query: { + bool: { + filter: [ + ...getDocumentTypeFilterForServiceMetrics(), + ...(start && end ? rangeQuery(start, end) : []), + ...kqlQuery(kuery), + ], + }, + }, + }, + terminate_after: 1, + } + ); + + return response.hits.total.value > 0; +} + +export function getDocumentTypeFilterForServiceMetrics() { + return [ + { + term: { + [METRICSET_NAME]: 'service', + }, + }, + ]; +} diff --git a/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.test.ts b/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.test.ts new file mode 100644 index 0000000000000..0905f39f183b4 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { calculateFailedTransactionRateFromServiceMetrics } from './transaction_error_rate'; + +describe('calculateFailedTransactionRateFromServiceMetrics', () => { + it('should return 0 when all params are null', () => { + expect( + calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: null, + successfulTransactions: null, + }) + ).toBe(0); + }); + + it('should return 9 when failedTransactions:null', () => { + expect( + calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: null, + successfulTransactions: 2, + }) + ).toBe(0); + }); + + it('should return 0 when failedTransactions:0', () => { + expect( + calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: 0, + successfulTransactions: null, + }) + ).toBe(0); + }); + + it('should return 1 when failedTransactions:10 and successfulTransactions:0', () => { + expect( + calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: 10, + successfulTransactions: 0, + }) + ).toBe(1); + }); + it('should return 0,5 when failedTransactions:10 and successfulTransactions:10', () => { + expect( + calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: 10, + successfulTransactions: 10, + }) + ).toBe(0.5); + }); +}); diff --git a/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts b/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts index 5631633b41b72..665784ce53454 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transaction_error_rate.ts @@ -9,15 +9,18 @@ import type { AggregationOptionsByType, AggregationResultOf, } from '@kbn/es-types'; +import { isNull } from 'lodash'; import { EVENT_OUTCOME } from '../../../common/elasticsearch_fieldnames'; import { EventOutcome } from '../../../common/event_outcome'; -export const getOutcomeAggregation = () => ({ - terms: { - field: EVENT_OUTCOME, - include: [EventOutcome.failure, EventOutcome.success], - }, -}); +export const getOutcomeAggregation = () => { + return { + terms: { + field: EVENT_OUTCOME, + include: [EventOutcome.failure, EventOutcome.success], + }, + }; +}; type OutcomeAggregation = ReturnType; @@ -48,6 +51,21 @@ export function calculateFailedTransactionRate( return failedTransactions / (successfulTransactions + failedTransactions); } +export function calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions, + successfulTransactions, +}: { + failedTransactions: number | null; + successfulTransactions: number | null; +}) { + if (isNull(failedTransactions) || failedTransactions === 0) { + return 0; + } + + successfulTransactions = successfulTransactions ?? 0; + return failedTransactions / (successfulTransactions + failedTransactions); +} + export function getFailedTransactionRateTimeSeries( buckets: AggregationResultOf< { diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/active_instances.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/active_instances.ts index 426132b39cc09..5a813ced8e8d5 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/active_instances.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/active_instances.ts @@ -13,7 +13,6 @@ import { SERVICE_NODE_NAME, } from '../../../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../../../common/utils/environment_query'; -import { getVizColorForIndex } from '../../../../../common/viz_colors'; import { getMetricsDateHistogramParams } from '../../../../lib/helpers/metrics'; import { Setup } from '../../../../lib/helpers/setup_request'; import { @@ -92,7 +91,14 @@ export async function getActiveInstances({ defaultMessage: 'Active instances', }), key: 'active_instances', - yUnit: 'number', + yUnit: 'integer', + description: i18n.translate( + 'xpack.apm.agentMetrics.serverless.activeInstances.description', + { + defaultMessage: + 'This chart shows the number of active instances of your serverless function over time. Multiple active instances may be a result of provisioned concurrency for your function or an increase in concurrent load that scales your function on-demand. An increase in active instance can be an indicator for an increase in concurrent invocations.', + } + ), series: [ { title: i18n.translate( @@ -100,8 +106,8 @@ export async function getActiveInstances({ { defaultMessage: 'Active instances' } ), key: 'active_instances', - type: 'linemark', - color: getVizColorForIndex(0, theme), + type: 'bar', + color: theme.euiColorVis1, overallValue: aggregations?.activeInstances.value ?? 0, data: aggregations?.timeseriesData.buckets.map((timeseriesBucket) => ({ diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_count.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_count.ts index fc94a59da9a22..d884aa8dce446 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_count.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_count.ts @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import { termQuery } from '@kbn/observability-plugin/server'; +import { euiLightVars as theme } from '@kbn/ui-theme'; import { FAAS_COLDSTART, METRICSET_NAME, @@ -20,13 +21,14 @@ const chartBase: ChartBase = { defaultMessage: 'Cold start', }), key: 'cold_start_count', - type: 'linemark', - yUnit: 'number', + type: 'bar', + yUnit: 'integer', series: { coldStart: { title: i18n.translate('xpack.apm.agentMetrics.serverless.coldStart', { defaultMessage: 'Cold start', }), + color: theme.euiColorVis5, }, }, }; diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_duration.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_duration.ts index 84fac7f99303e..e66d855d1be99 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_duration.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/cold_start_duration.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import { euiLightVars as theme } from '@kbn/ui-theme'; import { FAAS_COLDSTART_DURATION } from '../../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../../lib/helpers/setup_request'; import { fetchAndTransformMetrics } from '../../fetch_and_transform_metrics'; @@ -24,8 +25,16 @@ const chartBase: ChartBase = { 'xpack.apm.agentMetrics.serverless.coldStartDuration', { defaultMessage: 'Cold start duration' } ), + color: theme.euiColorVis5, }, }, + description: i18n.translate( + 'xpack.apm.agentMetrics.serverless.coldStartDuration.description', + { + defaultMessage: + 'Cold start duration shows the execution duration of the serverless runtime for requests that experience cold starts.', + } + ), }; export function getColdStartDuration({ diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/compute_usage.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/compute_usage.ts index da57498c8af02..b38e0665a77f2 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/compute_usage.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/compute_usage.ts @@ -21,27 +21,9 @@ import { } from '../../../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../../../common/utils/environment_query'; import { isFiniteNumber } from '../../../../../common/utils/is_finite_number'; -import { getVizColorForIndex } from '../../../../../common/viz_colors'; import { getMetricsDateHistogramParams } from '../../../../lib/helpers/metrics'; import { Setup } from '../../../../lib/helpers/setup_request'; import { GenericMetricsChart } from '../../fetch_and_transform_metrics'; -import { ChartBase } from '../../types'; - -const chartBase: ChartBase = { - title: i18n.translate('xpack.apm.agentMetrics.serverless.computeUsage', { - defaultMessage: 'Compute usage', - }), - key: 'compute_usage', - type: 'linemark', - yUnit: 'number', - series: { - computeUsage: { - title: i18n.translate('xpack.apm.agentMetrics.serverless.computeUsage', { - defaultMessage: 'Compute usage', - }), - }, - }, -}; /** * To calculate the compute usage we need to multiply the "system.memory.total" by "faas.billed_duration". @@ -126,9 +108,18 @@ export async function getComputeUsage({ const timeseriesData = aggregations?.timeseriesData; return { - title: chartBase.title, - key: chartBase.key, - yUnit: chartBase.yUnit, + title: i18n.translate('xpack.apm.agentMetrics.serverless.computeUsage', { + defaultMessage: 'Compute usage', + }), + key: 'compute_usage', + yUnit: 'number', + description: i18n.translate( + 'xpack.apm.agentMetrics.serverless.computeUsage.description', + { + defaultMessage: + "Compute usage (in GB-seconds) is the execution time multiplied by the available memory size of your function's instances. The compute usage is a direct indicator for the costs of your serverless function.", + } + ), series: !timeseriesData || timeseriesData.buckets.length === 0 ? [] @@ -139,12 +130,12 @@ export async function getComputeUsage({ { defaultMessage: 'Compute usage' } ), key: 'compute_usage', - type: 'linemark', + type: 'bar', overallValue: calculateComputeUsageGBSeconds({ faasBilledDuration: aggregations?.avgFaasBilledDuration.value, totalMemory: aggregations?.avgTotalMemory.value, }), - color: getVizColorForIndex(0, theme), + color: theme.euiColorVis0, data: timeseriesData.buckets.map((bucket) => { const computeUsage = calculateComputeUsageGBSeconds({ faasBilledDuration: bucket.avgFaasBilledDuration.value, diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts index a34165dc95f41..9200e9d07e1ce 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts @@ -51,9 +51,9 @@ export function getServerlessAgentMetricCharts({ ...options, searchAggregatedTransactions, }), + getMemoryChartData(options), getColdStartDuration(options), getColdStartCount(options), - getMemoryChartData(options), getComputeUsage(options), getActiveInstances({ ...options, searchAggregatedTransactions }), ]); diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/serverless_function_latency.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/serverless_function_latency.ts index 99a09c86e954f..0db9385615d2a 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/serverless_function_latency.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/serverless_function_latency.ts @@ -32,6 +32,13 @@ const chartBase: ChartBase = { type: 'linemark', yUnit: 'time', series: {}, + description: i18n.translate( + 'xpack.apm.agentMetrics.serverless.avgDuration.description', + { + defaultMessage: + 'Transaction duration is the time spent processing and responding to a request. If the request is queued it will not be contribute to the transaction duration but will contribute the overall billed duration', + } + ), }; async function getServerlessLantecySeries({ diff --git a/x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts index 9bc5fe20a72c8..b8faa6b140a4b 100644 --- a/x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts @@ -21,6 +21,7 @@ import { serviceNodeNameQuery, } from '../../../common/utils/environment_query'; import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; +import { ChartType, Coordinate, YUnit } from '../../../typings/timeseries'; type MetricsAggregationMap = Unionize<{ min: AggregationOptionsByType['min']; @@ -42,9 +43,22 @@ export type GenericMetricsRequest = APMEventESSearchRequest & { }; }; -export type GenericMetricsChart = Awaited< - ReturnType ->; +export type GenericMetricsChart = Awaited; + +export interface FetchAndTransformMetrics { + title: string; + key: string; + yUnit: YUnit; + series: Array<{ + title: string; + key: string; + type: ChartType; + color: string; + overallValue: number; + data: Coordinate[]; + }>; + description?: string; +} export async function fetchAndTransformMetrics({ environment, @@ -70,7 +84,7 @@ export async function fetchAndTransformMetrics({ aggs: T; additionalFilters?: QueryDslQueryContainer[]; operationName: string; -}) { +}): Promise { const { apmEventClient, config } = setup; const params: GenericMetricsRequest = { @@ -115,6 +129,7 @@ export async function fetchAndTransformMetrics({ title: chartBase.title, key: chartBase.key, yUnit: chartBase.yUnit, + description: chartBase.description, series: hits.total.value === 0 ? [] diff --git a/x-pack/plugins/apm/server/routes/metrics/route.ts b/x-pack/plugins/apm/server/routes/metrics/route.ts index f8b20ae4e0299..5d6b4f245c568 100644 --- a/x-pack/plugins/apm/server/routes/metrics/route.ts +++ b/x-pack/plugins/apm/server/routes/metrics/route.ts @@ -9,6 +9,7 @@ import * as t from 'io-ts'; import { setupRequest } from '../../lib/helpers/setup_request'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; +import { FetchAndTransformMetrics } from './fetch_and_transform_metrics'; import { getMetricsChartDataByAgent } from './get_metrics_chart_data_by_agent'; const metricsChartsRoute = createApmServerRoute({ @@ -34,19 +35,7 @@ const metricsChartsRoute = createApmServerRoute({ handler: async ( resources ): Promise<{ - charts: Array<{ - title: string; - key: string; - yUnit: import('./../../../typings/timeseries').YUnit; - series: Array<{ - title: string; - key: string; - type: import('./../../../typings/timeseries').ChartType; - color: string; - overallValue: number; - data: Array<{ x: number; y: number | null }>; - }>; - }>; + charts: FetchAndTransformMetrics[]; }> => { const { params } = resources; const setup = await setupRequest(resources); diff --git a/x-pack/plugins/apm/server/routes/metrics/types.ts b/x-pack/plugins/apm/server/routes/metrics/types.ts index 92ca587e3bdff..0cbf1cfce0916 100644 --- a/x-pack/plugins/apm/server/routes/metrics/types.ts +++ b/x-pack/plugins/apm/server/routes/metrics/types.ts @@ -18,4 +18,5 @@ export interface ChartBase { color?: string; }; }; + description?: string; } diff --git a/x-pack/plugins/apm/server/routes/services/get_services/get_service_aggregated_transaction_stats.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_service_aggregated_transaction_stats.ts new file mode 100644 index 0000000000000..d3364062eb2fb --- /dev/null +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_service_aggregated_transaction_stats.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { + AGENT_NAME, + SERVICE_ENVIRONMENT, + SERVICE_NAME, + TRANSACTION_TYPE, + TRANSACTION_DURATION_SUMMARY, + TRANSACTION_FAILURE_COUNT, + TRANSACTION_SUCCESS_COUNT, +} from '../../../../common/elasticsearch_fieldnames'; +import { + TRANSACTION_PAGE_LOAD, + TRANSACTION_REQUEST, +} from '../../../../common/transaction_types'; +import { environmentQuery } from '../../../../common/utils/environment_query'; +import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent'; +import { calculateThroughputWithRange } from '../../../lib/helpers/calculate_throughput'; +import { calculateFailedTransactionRateFromServiceMetrics } from '../../../lib/helpers/transaction_error_rate'; +import { ServicesItemsSetup } from './get_services_items'; +import { serviceGroupQuery } from '../../../lib/service_group_query'; +import { ServiceGroup } from '../../../../common/service_groups'; +import { RandomSampler } from '../../../lib/helpers/get_random_sampler'; +import { getDocumentTypeFilterForServiceMetrics } from '../../../lib/helpers/service_metrics'; +interface AggregationParams { + environment: string; + kuery: string; + setup: ServicesItemsSetup; + maxNumServices: number; + start: number; + end: number; + serviceGroup: ServiceGroup | null; + randomSampler: RandomSampler; +} + +export async function getServiceAggregatedTransactionStats({ + environment, + kuery, + setup, + maxNumServices, + start, + end, + serviceGroup, + randomSampler, +}: AggregationParams) { + const { apmEventClient } = setup; + + const response = await apmEventClient.search( + 'get_service_aggregated_transaction_stats', + { + apm: { + events: [ProcessorEvent.metric], + }, + body: { + size: 0, + query: { + bool: { + filter: [ + ...getDocumentTypeFilterForServiceMetrics(), + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ...serviceGroupQuery(serviceGroup), + ], + }, + }, + aggs: { + sample: { + random_sampler: randomSampler, + aggs: { + services: { + terms: { + field: SERVICE_NAME, + size: maxNumServices, + }, + aggs: { + transactionType: { + terms: { + field: TRANSACTION_TYPE, + }, + aggs: { + avg_duration: { + avg: { + field: TRANSACTION_DURATION_SUMMARY, + }, + }, + total_doc: { + value_count: { + field: TRANSACTION_DURATION_SUMMARY, + }, + }, + failure_count: { + sum: { + field: TRANSACTION_FAILURE_COUNT, + }, + }, + success_count: { + sum: { + field: TRANSACTION_SUCCESS_COUNT, + }, + }, + environments: { + terms: { + field: SERVICE_ENVIRONMENT, + }, + }, + sample: { + top_metrics: { + metrics: [{ field: AGENT_NAME } as const], + sort: { + '@timestamp': 'desc' as const, + }, + }, + }, + bucket_sort: { + bucket_sort: { + sort: [ + { + total_doc: { + order: 'desc', + }, + }, + ], + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + ); + + return ( + response.aggregations?.sample.services.buckets.map((bucket) => { + const topTransactionTypeBucket = + bucket.transactionType.buckets.find( + ({ key }) => + key === TRANSACTION_REQUEST || key === TRANSACTION_PAGE_LOAD + ) ?? bucket.transactionType.buckets[0]; + + return { + serviceName: bucket.key as string, + transactionType: topTransactionTypeBucket.key as string, + environments: topTransactionTypeBucket.environments.buckets.map( + (environmentBucket) => environmentBucket.key as string + ), + agentName: topTransactionTypeBucket.sample.top[0].metrics[ + AGENT_NAME + ] as AgentName, + latency: topTransactionTypeBucket.avg_duration.value, + transactionErrorRate: calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: topTransactionTypeBucket.failure_count.value, + successfulTransactions: topTransactionTypeBucket.success_count.value, + }), + throughput: calculateThroughputWithRange({ + start, + end, + value: topTransactionTypeBucket.total_doc.value, + }), + }; + }) ?? [] + ); +} diff --git a/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts index c8d83df9a700e..7ee41a2bea0e0 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts @@ -11,6 +11,7 @@ import { Setup } from '../../../lib/helpers/setup_request'; import { getHealthStatuses } from './get_health_statuses'; import { getServicesFromErrorAndMetricDocuments } from './get_services_from_error_and_metric_documents'; import { getServiceTransactionStats } from './get_service_transaction_stats'; +import { getServiceAggregatedTransactionStats } from './get_service_aggregated_transaction_stats'; import { mergeServiceStats } from './merge_service_stats'; import { ServiceGroup } from '../../../../common/service_groups'; import { RandomSampler } from '../../../lib/helpers/get_random_sampler'; @@ -24,6 +25,7 @@ export async function getServicesItems({ kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, logger, start, end, @@ -34,6 +36,7 @@ export async function getServicesItems({ kuery: string; setup: ServicesItemsSetup; searchAggregatedTransactions: boolean; + searchAggregatedServiceMetrics: boolean; logger: Logger; start: number; end: number; @@ -46,6 +49,7 @@ export async function getServicesItems({ kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, maxNumServices: MAX_NUMBER_OF_SERVICES, start, end, @@ -58,7 +62,9 @@ export async function getServicesItems({ servicesFromErrorAndMetricDocuments, healthStatuses, ] = await Promise.all([ - getServiceTransactionStats(params), + searchAggregatedServiceMetrics + ? getServiceAggregatedTransactionStats(params) + : getServiceTransactionStats(params), getServicesFromErrorAndMetricDocuments(params), getHealthStatuses(params).catch((err) => { logger.error(err); diff --git a/x-pack/plugins/apm/server/routes/services/get_services/index.ts b/x-pack/plugins/apm/server/routes/services/get_services/index.ts index 954da17c7249d..83932f630357e 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/index.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/index.ts @@ -17,6 +17,7 @@ export async function getServices({ kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, logger, start, end, @@ -27,6 +28,7 @@ export async function getServices({ kuery: string; setup: Setup; searchAggregatedTransactions: boolean; + searchAggregatedServiceMetrics: boolean; logger: Logger; start: number; end: number; @@ -39,6 +41,7 @@ export async function getServices({ kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, logger, start, end, diff --git a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_aggregated_transaction_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_aggregated_transaction_detailed_statistics.ts new file mode 100644 index 0000000000000..e1e1c84598eff --- /dev/null +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_aggregated_transaction_detailed_statistics.ts @@ -0,0 +1,244 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { keyBy } from 'lodash'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; +import { + SERVICE_NAME, + TRANSACTION_TYPE, + TRANSACTION_DURATION_SUMMARY, + TRANSACTION_FAILURE_COUNT, + TRANSACTION_SUCCESS_COUNT, +} from '../../../../common/elasticsearch_fieldnames'; +import { withApmSpan } from '../../../utils/with_apm_span'; +import { + TRANSACTION_PAGE_LOAD, + TRANSACTION_REQUEST, +} from '../../../../common/transaction_types'; +import { environmentQuery } from '../../../../common/utils/environment_query'; +import { getOffsetInMs } from '../../../../common/utils/get_offset_in_ms'; +import { calculateThroughputWithRange } from '../../../lib/helpers/calculate_throughput'; +import { getBucketSizeForAggregatedTransactions } from '../../../lib/helpers/get_bucket_size_for_aggregated_transactions'; +import { Setup } from '../../../lib/helpers/setup_request'; +import { calculateFailedTransactionRateFromServiceMetrics } from '../../../lib/helpers/transaction_error_rate'; +import { RandomSampler } from '../../../lib/helpers/get_random_sampler'; +import { getDocumentTypeFilterForServiceMetrics } from '../../../lib/helpers/service_metrics'; + +export async function getServiceAggregatedTransactionDetailedStats({ + serviceNames, + environment, + kuery, + setup, + searchAggregatedServiceMetrics, + offset, + start, + end, + randomSampler, +}: { + serviceNames: string[]; + environment: string; + kuery: string; + setup: Setup; + searchAggregatedServiceMetrics: boolean; + offset?: string; + start: number; + end: number; + randomSampler: RandomSampler; +}) { + const { apmEventClient } = setup; + const { offsetInMs, startWithOffset, endWithOffset } = getOffsetInMs({ + start, + end, + offset, + }); + + const metrics = { + avg_duration: { + avg: { + field: TRANSACTION_DURATION_SUMMARY, + }, + }, + total_doc: { + value_count: { + field: TRANSACTION_DURATION_SUMMARY, + }, + }, + failure_count: { + sum: { + field: TRANSACTION_FAILURE_COUNT, + }, + }, + success_count: { + sum: { + field: TRANSACTION_SUCCESS_COUNT, + }, + }, + }; + + const response = await apmEventClient.search( + 'get_service_aggregated_transaction_detail_stats', + { + apm: { + events: [ProcessorEvent.metric], + }, + body: { + size: 0, + query: { + bool: { + filter: [ + { terms: { [SERVICE_NAME]: serviceNames } }, + ...getDocumentTypeFilterForServiceMetrics(), + ...rangeQuery(startWithOffset, endWithOffset), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ], + }, + }, + aggs: { + sample: { + random_sampler: randomSampler, + aggs: { + services: { + terms: { + field: SERVICE_NAME, + size: serviceNames.length, + }, + aggs: { + transactionType: { + terms: { + field: TRANSACTION_TYPE, + }, + aggs: { + ...metrics, + timeseries: { + date_histogram: { + field: '@timestamp', + fixed_interval: + getBucketSizeForAggregatedTransactions({ + start: startWithOffset, + end: endWithOffset, + numBuckets: 20, + searchAggregatedServiceMetrics, + }).intervalString, + min_doc_count: 0, + extended_bounds: { + min: startWithOffset, + max: endWithOffset, + }, + }, + aggs: metrics, + }, + bucket_sort: { + bucket_sort: { + sort: [ + { + total_doc: { + order: 'desc', + }, + }, + ], + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + ); + + return keyBy( + response.aggregations?.sample.services.buckets.map((bucket) => { + const topTransactionTypeBucket = + bucket.transactionType.buckets.find( + ({ key }) => + key === TRANSACTION_REQUEST || key === TRANSACTION_PAGE_LOAD + ) ?? bucket.transactionType.buckets[0]; + + return { + serviceName: bucket.key as string, + latency: topTransactionTypeBucket.timeseries.buckets.map( + (dateBucket) => ({ + x: dateBucket.key + offsetInMs, + y: dateBucket.avg_duration.value, + }) + ), + transactionErrorRate: topTransactionTypeBucket.timeseries.buckets.map( + (dateBucket) => ({ + x: dateBucket.key + offsetInMs, + y: calculateFailedTransactionRateFromServiceMetrics({ + failedTransactions: dateBucket.failure_count.value, + successfulTransactions: dateBucket.success_count.value, + }), + }) + ), + throughput: topTransactionTypeBucket.timeseries.buckets.map( + (dateBucket) => ({ + x: dateBucket.key + offsetInMs, + y: calculateThroughputWithRange({ + start, + end, + value: dateBucket.total_doc.value, + }), + }) + ), + }; + }) ?? [], + 'serviceName' + ); +} + +export async function getServiceAggregatedDetailedStatsPeriods({ + serviceNames, + environment, + kuery, + setup, + searchAggregatedServiceMetrics, + offset, + start, + end, + randomSampler, +}: { + serviceNames: string[]; + environment: string; + kuery: string; + setup: Setup; + searchAggregatedServiceMetrics: boolean; + offset?: string; + start: number; + end: number; + randomSampler: RandomSampler; +}) { + return withApmSpan('get_service_aggregated_detailed_stats', async () => { + const commonProps = { + serviceNames, + environment, + kuery, + setup, + searchAggregatedServiceMetrics, + start, + end, + randomSampler, + }; + + const [currentPeriod, previousPeriod] = await Promise.all([ + getServiceAggregatedTransactionDetailedStats(commonProps), + offset + ? getServiceAggregatedTransactionDetailedStats({ + ...commonProps, + offset, + }) + : Promise.resolve({}), + ]); + + return { currentPeriod, previousPeriod }; + }); +} diff --git a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts index 600d3c71f7e08..a19d7e5984cf8 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts @@ -11,6 +11,7 @@ import { SERVICE_NAME, TRANSACTION_TYPE, } from '../../../../common/elasticsearch_fieldnames'; +import { withApmSpan } from '../../../utils/with_apm_span'; import { TRANSACTION_PAGE_LOAD, TRANSACTION_REQUEST, @@ -31,7 +32,7 @@ import { } from '../../../lib/helpers/transaction_error_rate'; import { RandomSampler } from '../../../lib/helpers/get_random_sampler'; -export async function getServiceTransactionDetailedStatistics({ +export async function getServiceTransactionDetailedStats({ serviceNames, environment, kuery, @@ -175,3 +176,50 @@ export async function getServiceTransactionDetailedStatistics({ 'serviceName' ); } + +export async function getServiceDetailedStatsPeriods({ + serviceNames, + environment, + kuery, + setup, + searchAggregatedTransactions, + offset, + start, + end, + randomSampler, +}: { + serviceNames: string[]; + environment: string; + kuery: string; + setup: Setup; + searchAggregatedTransactions: boolean; + offset?: string; + start: number; + end: number; + randomSampler: RandomSampler; +}) { + return withApmSpan('get_service_detailed_statistics', async () => { + const commonProps = { + serviceNames, + environment, + kuery, + setup, + searchAggregatedTransactions, + start, + end, + randomSampler, + }; + + const [currentPeriod, previousPeriod] = await Promise.all([ + getServiceTransactionDetailedStats(commonProps), + offset + ? getServiceTransactionDetailedStats({ + ...commonProps, + offset, + }) + : Promise.resolve({}), + ]); + + return { currentPeriod, previousPeriod }; + }); +} diff --git a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts index d75bf9d970c9c..b142b3484d559 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { withApmSpan } from '../../../utils/with_apm_span'; import { Setup } from '../../../lib/helpers/setup_request'; -import { getServiceTransactionDetailedStatistics } from './get_service_transaction_detailed_statistics'; +import { getServiceDetailedStatsPeriods } from './get_service_transaction_detailed_statistics'; +import { getServiceAggregatedDetailedStatsPeriods } from './get_service_aggregated_transaction_detailed_statistics'; import { RandomSampler } from '../../../lib/helpers/get_random_sampler'; export async function getServicesDetailedStatistics({ @@ -16,6 +16,7 @@ export async function getServicesDetailedStatistics({ kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, offset, start, end, @@ -26,30 +27,29 @@ export async function getServicesDetailedStatistics({ kuery: string; setup: Setup; searchAggregatedTransactions: boolean; + searchAggregatedServiceMetrics: boolean; offset?: string; start: number; end: number; randomSampler: RandomSampler; }) { - return withApmSpan('get_service_detailed_statistics', async () => { - const commonProps = { - serviceNames, - environment, - kuery, - setup, - searchAggregatedTransactions, - start, - end, - randomSampler, - }; - - const [currentPeriod, previousPeriod] = await Promise.all([ - getServiceTransactionDetailedStatistics(commonProps), - offset - ? getServiceTransactionDetailedStatistics({ ...commonProps, offset }) - : Promise.resolve({}), - ]); - - return { currentPeriod, previousPeriod }; - }); + const commonProps = { + serviceNames, + environment, + kuery, + setup, + start, + end, + randomSampler, + offset, + }; + return searchAggregatedServiceMetrics + ? getServiceAggregatedDetailedStatsPeriods({ + ...commonProps, + searchAggregatedServiceMetrics, + }) + : getServiceDetailedStatsPeriods({ + ...commonProps, + searchAggregatedTransactions, + }); } diff --git a/x-pack/plugins/apm/server/routes/services/queries.test.ts b/x-pack/plugins/apm/server/routes/services/queries.test.ts index d02a188d632a3..ff9f79867c2d7 100644 --- a/x-pack/plugins/apm/server/routes/services/queries.test.ts +++ b/x-pack/plugins/apm/server/routes/services/queries.test.ts @@ -54,6 +54,7 @@ describe('services queries', () => { getServicesItems({ setup, searchAggregatedTransactions: false, + searchAggregatedServiceMetrics: false, logger: {} as any, environment: ENVIRONMENT_ALL.value, kuery: '', diff --git a/x-pack/plugins/apm/server/routes/services/route.ts b/x-pack/plugins/apm/server/routes/services/route.ts index 4b76e53877d38..0c77c5b0be86f 100644 --- a/x-pack/plugins/apm/server/routes/services/route.ts +++ b/x-pack/plugins/apm/server/routes/services/route.ts @@ -19,6 +19,7 @@ import { Annotation } from '@kbn/observability-plugin/common/annotations'; import { apmServiceGroupMaxNumberOfServices } from '@kbn/observability-plugin/common'; import { latencyAggregationTypeRt } from '../../../common/latency_aggregation_types'; import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getServiceInventorySearchSource } from '../../lib/helpers/get_service_inventory_search_source'; import { setupRequest } from '../../lib/helpers/setup_request'; import { getServiceAnnotations } from './annotations'; import { getServices } from './get_services'; @@ -129,18 +130,23 @@ const servicesRoute = createApmServerRoute({ : Promise.resolve(null), getRandomSampler({ security, request, probability }), ]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ - ...setup, - kuery, - start, - end, - }); + + const { apmEventClient, config } = setup; + const { searchAggregatedTransactions, searchAggregatedServiceMetrics } = + await getServiceInventorySearchSource({ + config, + apmEventClient, + kuery, + start, + end, + }); return getServices({ environment, kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, logger, start, end, @@ -213,12 +219,15 @@ const servicesDetailedStatisticsRoute = createApmServerRoute({ getRandomSampler({ security, request, probability }), ]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ - ...setup, - start, - end, - kuery, - }); + const { apmEventClient, config } = setup; + const { searchAggregatedTransactions, searchAggregatedServiceMetrics } = + await getServiceInventorySearchSource({ + config, + apmEventClient, + kuery, + start, + end, + }); if (!serviceNames.length) { throw Boom.badRequest(`serviceNames cannot be empty`); @@ -229,6 +238,7 @@ const servicesDetailedStatisticsRoute = createApmServerRoute({ kuery, setup, searchAggregatedTransactions, + searchAggregatedServiceMetrics, offset, serviceNames, start, diff --git a/x-pack/plugins/apm/typings/timeseries.ts b/x-pack/plugins/apm/typings/timeseries.ts index b675873fc1d3c..2b2af4f3bff06 100644 --- a/x-pack/plugins/apm/typings/timeseries.ts +++ b/x-pack/plugins/apm/typings/timeseries.ts @@ -69,5 +69,5 @@ export interface APMChartSpec< groupId?: string; } -export type ChartType = 'area' | 'linemark'; +export type ChartType = 'area' | 'linemark' | 'bar'; export type YUnit = 'percent' | 'bytes' | 'number' | 'time' | 'integer'; diff --git a/x-pack/plugins/cases/public/components/all_cases/index.test.tsx b/x-pack/plugins/cases/public/components/all_cases/index.test.tsx index c17607918cb4f..6fd1556f7d4e1 100644 --- a/x-pack/plugins/cases/public/components/all_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/index.test.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; -import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; import { AllCases } from '.'; @@ -14,7 +13,6 @@ import { AppMockRenderer, createAppMockRenderer, noCreateCasesPermissions, - TestProviders, } from '../../common/mock'; import { useGetActionLicense } from '../../containers/use_get_action_license'; import { casesStatus, connectorsMock, useGetCasesMockState } from '../../containers/mock'; @@ -46,8 +44,7 @@ const useGetActionLicenseMock = useGetActionLicense as jest.Mock; const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock; const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock; -// FLAKY: https://github.com/elastic/kibana/issues/139677 -describe.skip('AllCases', () => { +describe('AllCases', () => { const refetchCases = jest.fn(); const setFilters = jest.fn(); const setQueryParams = jest.fn(); @@ -126,58 +123,33 @@ describe.skip('AllCases', () => { ...defaultGetCases, }); - const wrapper = mount( - - - - ); + const result = appMockRender.render(); + + await waitFor(() => { + expect(result.getByTestId('openStatsHeader')).toBeInTheDocument(); + expect(result.getByText('20')).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(result.getByTestId('inProgressStatsHeader')).toBeInTheDocument(); + expect(result.getByText('40')).toBeInTheDocument(); + }); await waitFor(() => { - expect(wrapper.find('[data-test-subj="openStatsHeader"]').exists()).toBeTruthy(); - expect( - wrapper - .find('[data-test-subj="openStatsHeader"] .euiDescriptionList__description') - .first() - .text() - ).toBe('20'); - - expect(wrapper.find('[data-test-subj="inProgressStatsHeader"]').exists()).toBeTruthy(); - expect( - wrapper - .find('[data-test-subj="inProgressStatsHeader"] .euiDescriptionList__description') - .first() - .text() - ).toBe('40'); - - expect(wrapper.find('[data-test-subj="closedStatsHeader"]').exists()).toBeTruthy(); - expect( - wrapper - .find('[data-test-subj="closedStatsHeader"] .euiDescriptionList__description') - .first() - .text() - ).toBe('130'); + expect(result.getByTestId('closedStatsHeader')).toBeInTheDocument(); + expect(result.getByText('130')).toBeInTheDocument(); }); }); it('should render the loading spinner when loading stats', async () => { useGetCasesStatusMock.mockReturnValue({ ...defaultCasesStatus, isLoading: true }); - const wrapper = mount( - - - - ); + const result = appMockRender.render(); await waitFor(() => { - expect( - wrapper.find('[data-test-subj="openStatsHeader-loading-spinner"]').exists() - ).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="inProgressStatsHeader-loading-spinner"]').exists() - ).toBeTruthy(); - expect( - wrapper.find('[data-test-subj="closedStatsHeader-loading-spinner"]').exists() - ).toBeTruthy(); + expect(result.getByTestId('openStatsHeader-loading-spinner')).toBeInTheDocument(); + expect(result.getByTestId('inProgressStatsHeader-loading-spinner')).toBeInTheDocument(); + expect(result.getByTestId('closedStatsHeader-loading-spinner')).toBeInTheDocument(); }); }); @@ -194,16 +166,10 @@ describe.skip('AllCases', () => { }, }); - const wrapper = mount( - - - - ); + const result = appMockRender.render(); await waitFor(() => { - expect( - wrapper.find('[data-test-subj="configure-case-button"]').first().prop('isDisabled') - ).toBeTruthy(); + expect(result.getByTestId('configure-case-button')).toBeDisabled(); }); }); @@ -220,16 +186,10 @@ describe.skip('AllCases', () => { }, }); - const wrapper = mount( - - - - ); + const result = appMockRender.render(); await waitFor(() => { - expect( - wrapper.find('[data-test-subj="configure-case-button"]').first().prop('isDisabled') - ).toBeFalsy(); + expect(result.getByTestId('configure-case-button')).not.toBeDisabled(); }); }); diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx index 8719ef2662954..a06ae9e772c11 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx @@ -427,6 +427,11 @@ describe('CaseViewPage', () => { }), }, }, + notifications: { + toasts: { + addDanger: () => {}, + }, + }, }, }), })); diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index df7c53e0bb320..240d14c4b573c 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -18,6 +18,7 @@ export const CSP_LATEST_FINDINGS_DATA_VIEW = 'logs-cloud_security_posture.findin export const FINDINGS_INDEX_NAME = 'logs-cloud_security_posture.findings'; export const FINDINGS_INDEX_PATTERN = 'logs-cloud_security_posture.findings-default*'; +export const FINDINGS_INDEX_DEFAULT_NS = 'logs-cloud_security_posture.findings-default'; export const LATEST_FINDINGS_INDEX_TEMPLATE_NAME = 'logs-cloud_security_posture.findings_latest'; export const LATEST_FINDINGS_INDEX_PATTERN = 'logs-cloud_security_posture.findings_latest-*'; diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 21c33c7f2603a..f4d8573beb4c1 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -85,18 +85,7 @@ export interface CspRulesStatus { export type AgentPolicyStatus = Pick & { agents: number }; export interface Benchmark { - package_policy: Pick< - PackagePolicy, - | 'id' - | 'name' - | 'policy_id' - | 'namespace' - | 'package' - | 'updated_at' - | 'updated_by' - | 'created_at' - | 'created_by' - >; + package_policy: PackagePolicy; agent_policy: AgentPolicyStatus; rules: CspRulesStatus; } diff --git a/x-pack/plugins/cloud_security_posture/kibana.json b/x-pack/plugins/cloud_security_posture/kibana.json index 059de58acc21e..4660b97445ce0 100755 --- a/x-pack/plugins/cloud_security_posture/kibana.json +++ b/x-pack/plugins/cloud_security_posture/kibana.json @@ -22,5 +22,6 @@ "cloud", "licensing" ], - "requiredBundles": ["kibanaReact"] + "requiredBundles": ["kibanaReact"], + "optionalPlugins": ["usageCollection"] } diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 8033d16d476c8..597e037cb68d8 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -6,8 +6,44 @@ */ import { euiPaletteForStatus } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../common/constants'; const [success, warning, danger] = euiPaletteForStatus(3); export const statusColors = { success, warning, danger }; export const CSP_MOMENT_FORMAT = 'MMMM D, YYYY @ HH:mm:ss.SSS'; + +export type CloudPostureIntegrations = typeof cloudPostureIntegrations; + +export const cloudPostureIntegrations = { + kspm: { + policyTemplate: 'kspm', + name: i18n.translate('xpack.csp.kspmIntegration.integration.nameTitle', { + defaultMessage: 'Kubernetes Security Posture Management', + }), + shortName: i18n.translate('xpack.csp.kspmIntegration.integration.shortNameTitle', { + defaultMessage: 'KSPM', + }), + options: [ + { + type: CLOUDBEAT_VANILLA, + name: i18n.translate('xpack.csp.kspmIntegration.vanillaOption.nameTitle', { + defaultMessage: 'Unmanaged Kubernetes', + }), + benchmark: i18n.translate('xpack.csp.kspmIntegration.vanillaOption.benchmarkTitle', { + defaultMessage: 'CIS Kubernetes', + }), + }, + { + type: CLOUDBEAT_EKS, + name: i18n.translate('xpack.csp.kspmIntegration.eksOption.nameTitle', { + defaultMessage: 'EKS (Elastic Kubernetes Service)', + }), + benchmark: i18n.translate('xpack.csp.kspmIntegration.eksOption.benchmarkTitle', { + defaultMessage: 'CIS EKS', + }), + }, + ], + }, +} as const; diff --git a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts new file mode 100644 index 0000000000000..6cc02ac9aedc1 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { cloudPostureIntegrations, CloudPostureIntegrations } from '../constants'; + +const isPolicyTemplate = (name: unknown): name is keyof CloudPostureIntegrations => + typeof name === 'string' && name in cloudPostureIntegrations; + +export const getEnabledCspIntegrationDetails = (packageInfo?: PackagePolicy) => { + const enabledInput = packageInfo?.inputs.find((input) => input.enabled); + if (!enabledInput || !isPolicyTemplate(enabledInput.policy_template)) return null; + + const integration = cloudPostureIntegrations[enabledInput.policy_template]; + const enabledIntegrationOption = integration.options.find( + (option) => option.type === enabledInput.type + ); + + return { integration, enabledIntegrationOption }; +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx index ab193ab6dc8be..0d838daa1e660 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx @@ -13,6 +13,10 @@ interface Props { type: 'passed' | 'failed'; } +// 'fail' / 'pass' are same chars length, but not same width size. +// 46px is used to make sure the badge is always the same width. +const BADGE_WIDTH = 46; + const getColor = (type: Props['type']): EuiBadgeProps['color'] => { if (type === 'passed') return 'success'; if (type === 'failed') return 'danger'; @@ -20,7 +24,7 @@ const getColor = (type: Props['type']): EuiBadgeProps['color'] => { }; export const CspEvaluationBadge = ({ type }: Props) => ( - + {type === 'failed' ? ( ) : ( diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_inline_description_list.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_inline_description_list.tsx new file mode 100644 index 0000000000000..7acb06d2eabb6 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_inline_description_list.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiDescriptionList, useEuiTheme, type EuiDescriptionListProps } from '@elastic/eui'; + +const getModifiedTitlesListItems = (listItems: EuiDescriptionListProps['listItems']) => + listItems + ?.filter((item) => !!item?.title && !!item?.description) + .map((item) => ({ ...item, title: `${item.title}:` })); + +// eui size m is 12px which is too small, and next after it is base which is 16px which is too big +const fontSize = '1rem'; + +export const CspInlineDescriptionList = ({ + listItems, +}: { + listItems: EuiDescriptionListProps['listItems']; +}) => { + const { euiTheme } = useEuiTheme(); + const modifiedTitlesListItems = getModifiedTitlesListItems(listItems); + + return ( + + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx index 3085f9d83ea86..b01b5073a0e1b 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx @@ -16,7 +16,7 @@ import { EuiDescribedFormGroup, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; +import { cloudPostureIntegrations } from '../../common/constants'; import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants'; export type InputType = typeof CLOUDBEAT_EKS | typeof CLOUDBEAT_VANILLA; @@ -27,22 +27,8 @@ interface Props { isDisabled?: boolean; } -const kubeDeployOptions: Array> = [ - { - value: CLOUDBEAT_VANILLA, - label: i18n.translate( - 'xpack.csp.createPackagePolicy.stepConfigure.integrationSettingsSection.vanillaKubernetesDeploymentOption', - { defaultMessage: 'Unmanaged Kubernetes' } - ), - }, - { - value: CLOUDBEAT_EKS, - label: i18n.translate( - 'xpack.csp.createPackagePolicy.stepConfigure.integrationSettingsSection.eksKubernetesDeploymentOption', - { defaultMessage: 'EKS (Elastic Kubernetes Service)' } - ), - }, -]; +const kubeDeployOptions: Array> = + cloudPostureIntegrations.kspm.options.map((o) => ({ value: o.type, label: o.name })); const KubernetesDeploymentFieldLabel = () => ( ', () => { expect(screen.getByText(item.package_policy.name)).toBeInTheDocument(); }); - it('renders benchmark name', () => { - const item = createCspBenchmarkIntegrationFixture(); - const benchmarks = [item]; - - render( - - - - ); - - expect(screen.getByText(item.package_policy.package!.title)).toBeInTheDocument(); - }); - it('renders agent policy name', () => { const agentPolicy = { id: chance.guid(), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx index 7797a9a55ef8c..df1a058de11b6 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks_table.tsx @@ -11,16 +11,19 @@ import { type EuiBasicTableProps, type Pagination, type CriteriaWithPagination, + EuiLink, } from '@elastic/eui'; import React from 'react'; -import { Link, useHistory, generatePath } from 'react-router-dom'; +import { generatePath } from 'react-router-dom'; import { pagePathGetters } from '@kbn/fleet-plugin/public'; import { i18n } from '@kbn/i18n'; +import type { PackagePolicy } from '@kbn/fleet-plugin/common'; import { TimestampTableCell } from '../../components/timestamp_table_cell'; import type { Benchmark } from '../../../common/types'; import { useKibana } from '../../common/hooks/use_kibana'; import { cloudPosturePages } from '../../common/navigation/constants'; import * as TEST_SUBJ from './test_subjects'; +import { getEnabledCspIntegrationDetails } from '../../common/utils/get_enabled_csp_integration_details'; interface BenchmarksTableProps extends Pick, 'loading' | 'error' | 'noItemsMessage' | 'sorting'>, @@ -31,64 +34,89 @@ interface BenchmarksTableProps } const AgentPolicyButtonLink = ({ name, id: policyId }: { name: string; id: string }) => { - const { http, application } = useKibana().services; + const { http } = useKibana().services; const [fleetBase, path] = pagePathGetters.policy_details({ policyId }); + + return {name}; +}; + +const IntegrationButtonLink = ({ + packageName, + policyId, + packagePolicyId, +}: { + packageName: string; + packagePolicyId: string; + policyId: string; +}) => { + const { application } = useKibana().services; + return ( - { - e.stopPropagation(); - e.preventDefault(); - application.navigateToApp('fleet', { path }); - }} + - {name} - + {packageName} + ); }; const BENCHMARKS_TABLE_COLUMNS: Array> = [ { field: 'package_policy.name', - name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.integrationColumnTitle', { - defaultMessage: 'Integration', + name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.integrationNameColumnTitle', { + defaultMessage: 'Integration Name', }), render: (packageName, benchmark) => ( - { - e.stopPropagation(); - }} - > - {packageName} - + ), truncateText: true, sortable: true, - 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.INTEGRATION, + 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.INTEGRATION_NAME, }, { field: 'rules.enabled', - name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.activeRulesColumnTitle', { - defaultMessage: 'Active Rules', + name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.rulesColumnTitle', { + defaultMessage: 'Rules', + }), + truncateText: true, + 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.RULES, + }, + { + field: 'package_policy', + name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.integrationColumnTitle', { + defaultMessage: 'Integration', }), + dataType: 'string', truncateText: true, - 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.ACTIVE_RULES, + sortable: true, + 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.INTEGRATION, + render: (field: PackagePolicy) => { + const enabledIntegration = getEnabledCspIntegrationDetails(field); + return enabledIntegration?.integration?.shortName || ' '; + }, }, { - field: 'package_policy.package.title', - name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.integrationTypeColumnTitle', { - defaultMessage: 'Integration Type', + field: 'package_policy', + name: i18n.translate('xpack.csp.benchmarks.benchmarksTable.deploymentTypeColumnTitle', { + defaultMessage: 'Deployment Type', }), dataType: 'string', truncateText: true, sortable: true, - 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.INTEGRATION_TYPE, + 'data-test-subj': TEST_SUBJ.BENCHMARKS_TABLE_COLUMNS.DEPLOYMENT_TYPE, + render: (field: PackagePolicy) => { + const enabledIntegration = getEnabledCspIntegrationDetails(field); + return enabledIntegration?.enabledIntegrationOption?.name || ' '; + }, }, { field: 'agent_policy.name', @@ -146,18 +174,6 @@ export const BenchmarksTable = ({ sorting, ...rest }: BenchmarksTableProps) => { - const history = useHistory(); - - const getRowProps: EuiBasicTableProps['rowProps'] = (benchmark) => ({ - onClick: () => - history.push( - generatePath(cloudPosturePages.rules.path, { - packagePolicyId: benchmark.package_policy.id, - policyId: benchmark.package_policy.policy_id, - }) - ), - }); - const pagination: Pagination = { pageIndex: Math.max(pageIndex - 1, 0), pageSize, @@ -173,7 +189,6 @@ export const BenchmarksTable = ({ data-test-subj={rest['data-test-subj']} items={benchmarks} columns={BENCHMARKS_TABLE_COLUMNS} - rowProps={getRowProps} itemId={(item) => [item.agent_policy.id, item.package_policy.id].join('/')} pagination={pagination} onChange={onChange} diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/test_subjects.ts b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/test_subjects.ts index 3680c92f5d42b..d1d27325f9f88 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/test_subjects.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/test_subjects.ts @@ -9,9 +9,10 @@ export const BENCHMARKS_PAGE_HEADER = 'benchmarks-page-header'; export const BENCHMARKS_TABLE_DATA_TEST_SUBJ = 'csp_benchmarks_table'; export const ADD_INTEGRATION_TEST_SUBJ = 'csp_add_integration'; export const BENCHMARKS_TABLE_COLUMNS = { + INTEGRATION_NAME: 'benchmarks-table-column-integration-name', + DEPLOYMENT_TYPE: 'benchmarks-table-column-deployment-type', + RULES: 'benchmarks-table-column-rules', INTEGRATION: 'benchmarks-table-column-integration', - ACTIVE_RULES: 'benchmarks-table-column-active-rules', - INTEGRATION_TYPE: 'benchmarks-table-column-integration_type', AGENT_POLICY: 'benchmarks-table-column-agent-policy', NUMBER_OF_AGENTS: 'benchmarks-table-column-number-of-agents', CREATED_BY: 'benchmarks-table-column-created-by', diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.tsx index 040b383707a97..3294ee8ec4965 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.tsx @@ -6,7 +6,7 @@ */ import React, { useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiBottomBar, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiBottomBar, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { Evaluation } from '../../../../common/types'; import { CloudPosturePageTitle } from '../../../components/cloud_posture_page_title'; @@ -103,11 +103,17 @@ export const LatestFindingsContainer = ({ dataView }: FindingsBaseProps) => { }} loading={findingsGroupByNone.isFetching} /> - + + + + + + {!error && } + + {error && } {!error && ( <> - {findingsGroupByNone.isSuccess && !!findingsGroupByNone.data.page.length && ( ({ - id: chance.word(), cluster_id: chance.guid(), + id: chance.word(), result: { expected: { source: {}, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_container.tsx index e71f04c8b57b1..e9ce59fe9f0c0 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_container.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; import { Route, Switch } from 'react-router-dom'; -import { EuiSpacer } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { Evaluation } from '../../../../common/types'; import { CloudPosturePageTitle } from '../../../components/cloud_posture_page_title'; @@ -103,22 +103,28 @@ const LatestFindingsByResource = ({ dataView }: FindingsBaseProps) => { }} loading={findingsGroupByResource.isFetching} /> - - + + + + } /> - } - /> - + + + + {!error && } + + {error && } {!error && ( <> - {findingsGroupByResource.isSuccess && !!findingsGroupByResource.data.page.length && ( value < 1000 ? value : numeral(value).format('0.0a'); @@ -101,55 +104,21 @@ const FindingsByResourceTableComponent = ({ const baseColumns: Array> = [ { + ...baseFindingsColumns['resource.id'], field: 'resource_id', - name: ( - - ), render: (resourceId: FindingsByResourcePage['resource_id']) => ( - + {resourceId} ), }, - { - field: 'resource.sub_type', - truncateText: true, - name: ( - - ), - }, - { - field: 'resource.name', - truncateText: true, - name: ( - - ), - }, - { - field: 'rule.benchmark.name', - truncateText: true, - name: ( - - ), - }, + baseFindingsColumns['resource.sub_type'], + baseFindingsColumns['resource.name'], + baseFindingsColumns['rule.benchmark.name'], { field: 'rule.section', truncateText: true, @@ -159,24 +128,16 @@ const baseColumns: Array> = defaultMessage="CIS Sections" /> ), - render: (sections: string[]) => sections.join(', '), - }, - { - field: 'cluster_id', - name: ( - - ), - truncateText: true, + render: (sections: string[]) => { + const items = sections.join(', '); + return ( + + <>{items} + + ); + }, }, + baseFindingsColumns.cluster_id, { field: 'failed_findings', width: '150px', diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx index aa86a586faf7e..75997efaf6294 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx @@ -5,11 +5,17 @@ * 2.0. */ import React from 'react'; -import { EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; +import { + EuiSpacer, + EuiButtonEmpty, + EuiPageHeader, + type EuiDescriptionListProps, +} from '@elastic/eui'; import { Link, useParams } from 'react-router-dom'; import { FormattedMessage } from '@kbn/i18n-react'; import { generatePath } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; +import { CspInlineDescriptionList } from '../../../../components/csp_inline_description_list'; import type { Evaluation } from '../../../../../common/types'; import { CspFinding } from '../../../../../common/schemas/csp_finding'; import { CloudPosturePageTitle } from '../../../../components/cloud_posture_page_title'; @@ -54,6 +60,32 @@ const BackToResourcesButton = () => ( ); +const getResourceFindingSharedValues = (sharedValues: { + resourceId: string; + resourceSubType: string; + resourceName: string; + clusterId: string; +}): EuiDescriptionListProps['listItems'] => [ + { + title: i18n.translate('xpack.csp.findings.resourceFindingsSharedValues.resourceTypeTitle', { + defaultMessage: 'Resource Type', + }), + description: sharedValues.resourceSubType, + }, + { + title: i18n.translate('xpack.csp.findings.resourceFindingsSharedValues.resourceIdTitle', { + defaultMessage: 'Resource ID', + }), + description: sharedValues.resourceId, + }, + { + title: i18n.translate('xpack.csp.findings.resourceFindingsSharedValues.clusterIdTitle', { + defaultMessage: 'Cluster ID', + }), + description: sharedValues.clusterId, + }, +]; + export const ResourceFindings = ({ dataView }: FindingsBaseProps) => { const params = useParams<{ resourceId: string }>(); const getPersistedDefaultQuery = usePersistedQuery(getDefaultQuery); @@ -114,14 +146,28 @@ export const ResourceFindings = ({ dataView }: FindingsBaseProps) => { title={i18n.translate( 'xpack.csp.findings.resourceFindings.resourceFindingsPageTitle', { - defaultMessage: '{resourceId} - Findings', - values: { resourceId: params.resourceId }, + defaultMessage: '{resourceName} - Findings', + values: { resourceName: resourceFindings.data?.resourceName }, } )} /> } /> + + ) + } + /> {error && } {!error && ( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_table.tsx index c8dddf5ebd84e..976ddd8d8b37f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_table.tsx @@ -49,25 +49,16 @@ const ResourceFindingsTableComponent = ({ ] = useMemo( () => [ getExpandColumn({ onClick: setSelectedFinding }), - baseFindingsColumns['resource.id'], createColumnWithFilters(baseFindingsColumns['result.evaluation'], { onAddFilter }), - createColumnWithFilters( - { ...baseFindingsColumns['resource.sub_type'], sortable: false }, - { onAddFilter } - ), - createColumnWithFilters( - { ...baseFindingsColumns['resource.name'], sortable: false }, - { onAddFilter } - ), createColumnWithFilters(baseFindingsColumns['rule.name'], { onAddFilter }), createColumnWithFilters(baseFindingsColumns['rule.benchmark.name'], { onAddFilter }), baseFindingsColumns['rule.section'], baseFindingsColumns['rule.tags'], - createColumnWithFilters(baseFindingsColumns.cluster_id, { onAddFilter }), baseFindingsColumns['@timestamp'], ], [onAddFilter] ); + if (!loading && !items.length) return ( ; -type ResourceFindingsResponse = IKibanaSearchResponse>; +type ResourceFindingsResponse = IKibanaSearchResponse< + estypes.SearchResponse +>; -interface Aggs { - count: estypes.AggregationsMultiBucketAggregateBase; -} +export type ResourceFindingsResponseAggs = Record< + 'count' | 'clusterId' | 'resourceSubType' | 'resourceName', + estypes.AggregationsMultiBucketAggregateBase +>; const getResourceFindingsQuery = ({ query, @@ -60,7 +63,18 @@ const getResourceFindingsQuery = ({ }, sort: [{ [sort.field]: sort.direction }], pit: { id: pitId }, - aggs: getFindingsCountAggQuery(), + aggs: { + ...getFindingsCountAggQuery(), + clusterId: { + terms: { field: 'cluster_id' }, + }, + resourceSubType: { + terms: { field: 'resource.sub_type' }, + }, + resourceName: { + terms: { field: 'resource.name' }, + }, + }, }, ignore_unavailable: false, }); @@ -90,13 +104,18 @@ export const useResourceFindings = (options: UseResourceFindingsOptions) => { }: ResourceFindingsResponse) => { if (!aggregations) throw new Error('expected aggregations to exists'); - if (!Array.isArray(aggregations?.count.buckets)) - throw new Error('expected buckets to be an array'); + assertNonEmptyArray(aggregations.count.buckets); + assertNonEmptyArray(aggregations.clusterId.buckets); + assertNonEmptyArray(aggregations.resourceSubType.buckets); + assertNonEmptyArray(aggregations.resourceName.buckets); return { page: hits.hits.map((hit) => hit._source!), total: number.is(hits.total) ? hits.total : 0, count: getAggregationCount(aggregations.count.buckets), + clusterId: getFirstBucketKey(aggregations.clusterId.buckets), + resourceSubType: getFirstBucketKey(aggregations.resourceSubType.buckets), + resourceName: getFirstBucketKey(aggregations.resourceName.buckets), newPitId: newPitId!, }; }, @@ -110,3 +129,12 @@ export const useResourceFindings = (options: UseResourceFindingsOptions) => { } ); }; + +function assertNonEmptyArray(arr: unknown): asserts arr is T[] { + if (!Array.isArray(arr) || arr.length === 0) { + throw new Error('expected a non empty array'); + } +} + +const getFirstBucketKey = (buckets: estypes.AggregationsStringRareTermsBucketKeys[]) => + buckets[0].key; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_layout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_layout.tsx index 8e158d47e615b..ff7be4d7429ad 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_layout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_layout.tsx @@ -76,7 +76,7 @@ const baseColumns = [ /> ), truncateText: true, - width: '10%', + width: '150px', sortable: true, render: (filename: string) => ( @@ -89,7 +89,7 @@ const baseColumns = [ name: i18n.translate('xpack.csp.findings.findingsTable.findingsTableColumn.resultColumnLabel', { defaultMessage: 'Result', }), - width: '110px', + width: '120px', sortable: true, render: (type: PropsOf['type']) => ( @@ -103,6 +103,7 @@ const baseColumns = [ ), sortable: true, truncateText: true, + width: '10%', }, { field: 'resource.name', @@ -112,6 +113,11 @@ const baseColumns = [ ), sortable: true, truncateText: true, + render: (name: string) => ( + + <>{name} + + ), }, { field: 'rule.name', @@ -119,6 +125,11 @@ const baseColumns = [ defaultMessage: 'Rule', }), sortable: true, + render: (name: string) => ( + + <>{name} + + ), }, { field: 'rule.benchmark.name', @@ -126,6 +137,7 @@ const baseColumns = [ 'xpack.csp.findings.findingsTable.findingsTableColumn.ruleBenchmarkColumnLabel', { defaultMessage: 'Benchmark' } ), + width: '10%', sortable: true, truncateText: true, }, @@ -135,8 +147,14 @@ const baseColumns = [ 'xpack.csp.findings.findingsTable.findingsTableColumn.ruleSectionColumnLabel', { defaultMessage: 'CIS Section' } ), + width: '7%', sortable: true, truncateText: true, + render: (section: string) => ( + + <>{section} + + ), }, { field: 'rule.tags', @@ -144,7 +162,7 @@ const baseColumns = [ 'xpack.csp.findings.findingsTable.findingsTableColumn.ruleTagsColumnLabel', { defaultMessage: 'Rule Tags' } ), - width: '200px', + width: '15%', sortable: false, truncateText: true, render: (tags: string[]) => { @@ -166,13 +184,18 @@ const baseColumns = [ )} /> ), - width: '10%', - truncateText: true, + width: '150px', sortable: true, + truncateText: true, + render: (section: string) => ( + + <>{section} + + ), }, { field: '@timestamp', - width: '150px', + width: '10%', name: i18n.translate( 'xpack.csp.findings.findingsTable.findingsTableColumn.lastCheckedColumnLabel', { defaultMessage: 'Last Checked' } diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx index 57e3da3658a2e..edb41a0535f16 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx @@ -7,10 +7,19 @@ import React, { useContext, useMemo } from 'react'; import { generatePath, Link, type RouteComponentProps } from 'react-router-dom'; -import { EuiTextColor, EuiButtonEmpty, EuiFlexGroup, EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { + EuiButtonEmpty, + type EuiDescriptionListProps, + EuiFlexGroup, + EuiPageHeader, + EuiSpacer, + EuiFlexItem, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { pagePathGetters } from '@kbn/fleet-plugin/public'; import { i18n } from '@kbn/i18n'; +import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { CspInlineDescriptionList } from '../../components/csp_inline_description_list'; import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title'; import type { BreadcrumbEntry } from '../../common/navigation/types'; import { RulesContainer, type PageUrlParams } from './rules_container'; @@ -20,6 +29,8 @@ import { useCspIntegrationInfo } from './use_csp_integration'; import { useKibana } from '../../common/hooks/use_kibana'; import { CloudPosturePage } from '../../components/cloud_posture_page'; import { SecuritySolutionContext } from '../../application/security_solution_context'; +import * as TEST_SUBJECTS from './test_subjects'; +import { getEnabledCspIntegrationDetails } from '../../common/utils/get_enabled_csp_integration_details'; const getRulesBreadcrumbs = ( name?: string, @@ -41,12 +52,47 @@ const getRulesBreadcrumbs = ( return breadCrumbs; }; +const getRulesSharedValues = ( + packageInfo?: PackagePolicy +): NonNullable => { + const enabledIntegration = getEnabledCspIntegrationDetails(packageInfo); + const values = []; + + if (enabledIntegration?.integration?.shortName) { + values.push({ + title: i18n.translate('xpack.csp.rules.rulesPageSharedValues.integrationTitle', { + defaultMessage: 'Integration', + }), + description: enabledIntegration?.integration.shortName, + }); + } + + if (!enabledIntegration?.enabledIntegrationOption) return values; + + values.push( + { + title: i18n.translate('xpack.csp.rules.rulesPageSharedValues.deploymentTypeTitle', { + defaultMessage: 'Deployment Type', + }), + description: enabledIntegration?.enabledIntegrationOption.name, + }, + { + title: i18n.translate('xpack.csp.rules.rulesPageSharedValues.benchmarkTitle', { + defaultMessage: 'Benchmark', + }), + description: enabledIntegration?.enabledIntegrationOption.benchmark, + } + ); + + return values; +}; + export const Rules = ({ match: { params } }: RouteComponentProps) => { const { http } = useKibana().services; const integrationInfo = useCspIntegrationInfo(params); const securitySolutionContext = useContext(SecuritySolutionContext); - const [packageInfo, agentInfo] = integrationInfo.data || []; + const [packageInfo] = integrationInfo.data || []; const breadcrumbs = useMemo( () => @@ -56,10 +102,44 @@ export const Rules = ({ match: { params } }: RouteComponentProps) useCspBreadcrumbs(breadcrumbs); + const sharedValues = getRulesSharedValues(packageInfo); + return ( + + + + + + + + + + + + } + description={ + sharedValues.length && ( +
+ +
+ ) + } rightSideItems={[ ) /> , ]} - pageTitle={ - - - - - - - - - } - description={ - packageInfo?.package && - agentInfo?.name && ( - - - - ) - } - bottomBorder /> diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx index 70d803ff4ac5e..45e19b9fba5bd 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx @@ -105,6 +105,18 @@ describe('', () => { package: { title: 'my package', }, + inputs: [ + { + enabled: true, + policy_template: 'kspm', + type: 'cloudbeat/cis_k8s', + }, + { + enabled: false, + policy_template: 'kspm', + type: 'cloudbeat/cis_eks', + }, + ], }, { name: 'my agent' }, ], @@ -114,9 +126,7 @@ describe('', () => { render(); - expect( - await screen.findByText(`${response.data?.[0]?.package?.title}, ${response.data?.[1].name}`) - ).toBeInTheDocument(); expect(await screen.findByTestId(TEST_SUBJECTS.CSP_RULES_CONTAINER)).toBeInTheDocument(); + expect(await screen.findByTestId(TEST_SUBJECTS.CSP_RULES_SHARED_VALUES)).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts index 9092bc1707fdc..a40ccff5b5e6e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/test_subjects.ts @@ -6,6 +6,9 @@ */ export const CSP_RULES_CONTAINER = 'csp_rules_container'; +export const CSP_RULES_SHARED_VALUES = 'csp_rules_shared_values'; +export const CSP_RULES_TABLE_ITEM_SWITCH = 'csp_rules_table_item_switch'; +export const CSP_RULES_SAVE_BUTTON = 'csp_rules_table_save_button'; export const CSP_RULES_TABLE = 'csp_rules_table'; export const CSP_RULES_TABLE_ROW_ITEM_NAME = 'csp_rules_table_row_item_name'; export const CSP_RULES_FLYOUT_CONTAINER = 'csp_rules_flyout_container'; diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts index 2f05049c4fe15..496b73f7bbef0 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts @@ -17,6 +17,8 @@ type CreateCspBenchmarkIntegrationFixtureInput = { export const createCspBenchmarkIntegrationFixture = ({ chance = new Chance(), package_policy = { + revision: chance?.integer(), + enabled: true, id: chance.guid(), name: chance.string(), policy_id: chance.guid(), @@ -25,6 +27,23 @@ export const createCspBenchmarkIntegrationFixture = ({ updated_by: chance.word(), created_at: chance.date().toISOString(), created_by: chance.word(), + inputs: [ + { + type: 'cloudbeat/cis_k8s', + policy_template: 'kspm', + enabled: true, + streams: [ + { + id: chance?.guid(), + enabled: true, + data_stream: { + type: 'logs', + dataset: 'cloud_security_posture.findings', + }, + }, + ], + }, + ], package: { name: chance.string(), title: chance.string(), diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/indices_stats_collector.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/indices_stats_collector.ts new file mode 100644 index 0000000000000..a1bb49216262f --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/indices_stats_collector.ts @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { Logger } from '@kbn/core/server'; +import { + BENCHMARK_SCORE_INDEX_DEFAULT_NS, + FINDINGS_INDEX_DEFAULT_NS, + LATEST_FINDINGS_INDEX_DEFAULT_NS, +} from '../../../../common/constants'; +import type { CspmIndicesStats, IndexStats } from './types'; + +export const getIndicesStats = async ( + esClient: ElasticsearchClient, + logger: Logger +): Promise => { + const [findings, latestFindings, score] = await Promise.all([ + getIndexStats(esClient, FINDINGS_INDEX_DEFAULT_NS, logger), + getIndexStats(esClient, LATEST_FINDINGS_INDEX_DEFAULT_NS, logger), + getIndexStats(esClient, BENCHMARK_SCORE_INDEX_DEFAULT_NS, logger), + ]); + return { + findings, + latest_findings: latestFindings, + score, + }; +}; + +const getIndexStats = async ( + esClient: ElasticsearchClient, + index: string, + logger: Logger +): Promise => { + try { + const isIndexExists = await esClient.indices.exists({ + index, + }); + + if (isIndexExists) { + const indexStats = await getIndexDocCount(esClient, index); + return { + doc_count: indexStats._all.primaries?.docs ? indexStats._all.primaries?.docs?.count : 0, + deleted: indexStats._all.primaries?.docs?.deleted + ? indexStats._all.primaries?.docs?.deleted + : 0, + size_in_bytes: indexStats._all.primaries?.store + ? indexStats._all.primaries?.store.size_in_bytes + : 0, + last_doc_timestamp: await getLatestDocTimestamp(esClient, index), + }; + } + + return {}; + } catch (e) { + logger.error(`Failed to get index stats for ${index}`); + return {}; + } +}; + +const getIndexDocCount = (esClient: ElasticsearchClient, index: string) => + esClient.indices.stats({ index }); + +const getLatestDocTimestamp = async ( + esClient: ElasticsearchClient, + index: string +): Promise => { + const latestTimestamp = await esClient.search({ + index, + query: { + match_all: {}, + }, + sort: '@timestamp:desc', + size: 1, + fields: ['@timestamp'], + _source: false, + }); + + const latestEventTimestamp = latestTimestamp.hits?.hits[0]?.fields; + + return latestEventTimestamp ? latestEventTimestamp['@timestamp'][0] : null; +}; diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/register.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/register.ts new file mode 100644 index 0000000000000..496890ca477d1 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/register.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 { CollectorFetchContext, UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import type { Logger } from '@kbn/core/server'; +import { getIndicesStats } from './indices_stats_collector'; +import { cspmUsageSchema } from './schema'; +import { CspmUsage } from './types'; + +export function registerCspmUsageCollector( + logger: Logger, + usageCollection?: UsageCollectionSetup +): void { + // usageCollection is an optional dependency, so make sure to return if it is not registered + if (!usageCollection) { + return; + } + + // Create usage collector + const cspmUsageCollector = usageCollection.makeUsageCollector({ + type: 'cloud_security_posture', + isReady: () => true, + fetch: async (collectorFetchContext: CollectorFetchContext) => { + const indicesStats = await getIndicesStats(collectorFetchContext.esClient, logger); + return { + indices: indicesStats, + }; + }, + schema: cspmUsageSchema, + }); + + // Register usage collector + usageCollection.registerCollector(cspmUsageCollector); +} diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/schema.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/schema.ts new file mode 100644 index 0000000000000..184963fc9a5d1 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/schema.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { MakeSchemaFrom } from '@kbn/usage-collection-plugin/server'; +import type { CspmUsage } from './types'; + +export const cspmUsageSchema: MakeSchemaFrom = { + indices: { + findings: { + doc_count: { + type: 'long', + }, + deleted: { + type: 'long', + }, + size_in_bytes: { + type: 'long', + }, + last_doc_timestamp: { + type: 'date', + }, + }, + latest_findings: { + doc_count: { + type: 'long', + }, + deleted: { + type: 'long', + }, + size_in_bytes: { + type: 'long', + }, + last_doc_timestamp: { + type: 'date', + }, + }, + score: { + doc_count: { + type: 'long', + }, + deleted: { + type: 'long', + }, + size_in_bytes: { + type: 'long', + }, + last_doc_timestamp: { + type: 'date', + }, + }, + }, +}; diff --git a/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts new file mode 100644 index 0000000000000..4cbb32578bf9a --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/server/lib/telemetry/collectors/types.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export interface CspmUsage { + indices: CspmIndicesStats; +} + +export interface CspmIndicesStats { + findings: IndexStats | {}; + latest_findings: IndexStats | {}; + score: IndexStats | {}; +} + +export interface IndexStats { + doc_count: number; + deleted: number; + size_in_bytes: number; + last_doc_timestamp: string | null; +} diff --git a/x-pack/plugins/cloud_security_posture/server/plugin.ts b/x-pack/plugins/cloud_security_posture/server/plugin.ts index 4603f42a0e09e..ba421346ae5db 100755 --- a/x-pack/plugins/cloud_security_posture/server/plugin.ts +++ b/x-pack/plugins/cloud_security_posture/server/plugin.ts @@ -52,6 +52,7 @@ import { scheduleFindingsStatsTask, setupFindingsStatsTask, } from './tasks/findings_stats_task'; +import { registerCspmUsageCollector } from './lib/telemetry/collectors/register'; export class CspPlugin implements @@ -82,6 +83,7 @@ export class CspPlugin const coreStartServices = core.getStartServices(); this.setupCspTasks(plugins.taskManager, coreStartServices, this.logger); + registerCspmUsageCollector(this.logger, plugins.usageCollection); this.isCloudEnabled = plugins.cloud.isCloudEnabled; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index a950741ea2d8f..49c392d724c25 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -14,11 +14,7 @@ import { getCspPackagePolicies, getCspAgentPolicies, } from '../../lib/fleet_util'; -import { - defineGetBenchmarksRoute, - createBenchmarkEntry, - addPackagePolicyCspRules, -} from './benchmarks'; +import { defineGetBenchmarksRoute, addPackagePolicyCspRules } from './benchmarks'; import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; import { @@ -26,28 +22,8 @@ import { createPackagePolicyServiceMock, } from '@kbn/fleet-plugin/server/mocks'; import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; -import { AgentPolicy } from '@kbn/fleet-plugin/common'; import { createCspRequestHandlerContextMock } from '../../mocks'; -function createMockAgentPolicy(props: Partial = {}): AgentPolicy { - return { - id: 'some-uuid1', - namespace: 'default', - monitoring_enabled: [], - name: 'Test Policy', - description: '', - is_default: false, - is_preconfigured: false, - status: 'active', - is_managed: false, - revision: 1, - updated_at: '', - updated_by: 'elastic', - package_policies: [], - ...props, - }; -} - describe('benchmarks API', () => { beforeEach(() => { jest.clearAllMocks(); @@ -307,51 +283,5 @@ describe('benchmarks API', () => { }); }); }); - - describe('test createBenchmarkEntry', () => { - it('should build benchmark entry agent policy and package policy', async () => { - const packagePolicy = createPackagePolicyMock(); - const agentPolicy = createMockAgentPolicy(); - - const cspRulesStatus = { - all: 100, - enabled: 52, - disabled: 48, - }; - const enrichAgentPolicy = await createBenchmarkEntry( - { - id: agentPolicy.id, - name: agentPolicy.name, - agents: 3, - }, - packagePolicy, - cspRulesStatus - ); - - expect(enrichAgentPolicy).toEqual({ - package_policy: { - id: 'c6d16e42-c32d-4dce-8a88-113cfe276ad1', - name: 'endpoint-1', - policy_id: '93c46720-c217-11ea-9906-b5b8a21b268e', - namespace: 'default', - updated_at: '2020-06-25T16:03:38.159292', - updated_by: 'kibana', - created_at: '2020-06-25T16:03:38.159292', - created_by: 'kibana', - package: { - name: 'endpoint', - title: 'Elastic Endpoint', - version: '0.9.0', - }, - }, - agent_policy: { id: 'some-uuid1', name: 'Test Policy', agents: 3 }, - rules: { - all: 100, - disabled: 48, - enabled: 52, - }, - }); - }); - }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index 4bc00f5e0209d..dec553cee6f75 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -13,7 +13,7 @@ import { CSP_RULE_SAVED_OBJECT_TYPE, } from '../../../common/constants'; import { benchmarksQueryParamsSchema } from '../../../common/schemas/benchmark'; -import type { Benchmark, CspRulesStatus, AgentPolicyStatus } from '../../../common/types'; +import type { Benchmark, CspRulesStatus } from '../../../common/types'; import type { CspRule } from '../../../common/schemas'; import { createCspRuleSearchFilterByPackagePolicy, @@ -74,32 +74,6 @@ export const addPackagePolicyCspRules = async ( return packagePolicyRules; }; -export const createBenchmarkEntry = ( - agentPolicyStatus: AgentPolicyStatus, - packagePolicy: PackagePolicy, - cspRulesStatus: CspRulesStatus -): Benchmark => ({ - package_policy: { - id: packagePolicy.id, - name: packagePolicy.name, - policy_id: packagePolicy.policy_id, - namespace: packagePolicy.namespace, - updated_at: packagePolicy.updated_at, - updated_by: packagePolicy.updated_by, - created_at: packagePolicy.created_at, - created_by: packagePolicy.created_by, - package: packagePolicy.package - ? { - name: packagePolicy.package.name, - title: packagePolicy.package.title, - version: packagePolicy.package.version, - } - : undefined, - }, - agent_policy: agentPolicyStatus, - rules: cspRulesStatus, -}); - const createBenchmarks = ( soClient: SavedObjectsClientContract, agentPolicies: AgentPolicy[], @@ -109,6 +83,7 @@ const createBenchmarks = ( const cspPackagePoliciesMap = new Map( cspPackagePolicies.map((packagePolicy) => [packagePolicy.id, packagePolicy]) ); + return Promise.all( agentPolicies.flatMap((agentPolicy) => { const cspPackagesOnAgent = @@ -117,6 +92,7 @@ const createBenchmarks = ( return cspPackagePoliciesMap.get(pckPolicyId); }) .filter(isNonNullable) ?? []; + const benchmarks = cspPackagesOnAgent.map(async (cspPackage) => { const cspRulesStatus = await addPackagePolicyCspRules(soClient, cspPackage); const agentPolicyStatus = { @@ -124,8 +100,12 @@ const createBenchmarks = ( name: agentPolicy.name, agents: agentStatusByAgentPolicyId[agentPolicy.id].total, }; - const benchmark = createBenchmarkEntry(agentPolicyStatus, cspPackage, cspRulesStatus); - return benchmark; + + return { + package_policy: cspPackage, + agent_policy: agentPolicyStatus, + rules: cspRulesStatus, + }; }); return benchmarks; diff --git a/x-pack/plugins/cloud_security_posture/server/types.ts b/x-pack/plugins/cloud_security_posture/server/types.ts index 115e353b50d51..ba69b8402bde0 100644 --- a/x-pack/plugins/cloud_security_posture/server/types.ts +++ b/x-pack/plugins/cloud_security_posture/server/types.ts @@ -31,6 +31,7 @@ import type { AgentPolicyServiceInterface, PackagePolicyClient, } from '@kbn/fleet-plugin/server'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { FleetStartContract, FleetRequestHandlerContext } from '@kbn/fleet-plugin/server'; import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; @@ -46,6 +47,7 @@ export interface CspServerPluginSetupDeps { security: SecurityPluginSetup; cloud: CloudSetup; // optional + usageCollection?: UsageCollectionSetup; } export interface CspServerPluginStartDeps { diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts index 75dd3fdfe8dce..ab8b03840c819 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts @@ -870,6 +870,44 @@ describe('#delete', () => { }); }); +describe('#bulkDelete', () => { + const obj1 = Object.freeze({ type: 'unknown-type', id: 'unknown-type-id-1' }); + const obj2 = Object.freeze({ type: 'unknown-type', id: 'unknown-type-id-2' }); + const namespace = 'some-ns'; + + it('redirects request to underlying base client if type is not registered', async () => { + await wrapper.bulkDelete([obj1, obj2], { namespace }); + expect(mockBaseClient.bulkDelete).toHaveBeenCalledTimes(1); + expect(mockBaseClient.bulkDelete).toHaveBeenCalledWith([obj1, obj2], { namespace }); + }); + + it('redirects request to underlying base client if type is registered', async () => { + const knownObj1 = Object.freeze({ type: 'known-type', id: 'known-type-id-1' }); + const knownObj2 = Object.freeze({ type: 'known-type', id: 'known-type-id-2' }); + const options = { namespace: 'some-ns' }; + + await wrapper.bulkDelete([knownObj1, knownObj2], options); + + expect(mockBaseClient.bulkDelete).toHaveBeenCalledTimes(1); + expect(mockBaseClient.bulkDelete).toHaveBeenCalledWith([knownObj1, knownObj2], { namespace }); + }); + + it('fails if base client fails', async () => { + const failureReason = new Error('Something bad happened...'); + mockBaseClient.bulkDelete.mockRejectedValue(failureReason); + + await expect(wrapper.bulkDelete([{ type: 'known-type', id: 'some-id' }])).rejects.toThrowError( + failureReason + ); + + expect(mockBaseClient.bulkDelete).toHaveBeenCalledTimes(1); + expect(mockBaseClient.bulkDelete).toHaveBeenCalledWith( + [{ type: 'known-type', id: 'some-id' }], + undefined + ); + }); +}); + describe('#find', () => { it('redirects request to underlying base client and does not alter response if type is not registered', async () => { const mockedResponse = { diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts index 0b9c81cc33334..e2fcfd2a6ef25 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts @@ -10,6 +10,8 @@ import type { SavedObject, SavedObjectsBaseOptions, SavedObjectsBulkCreateObject, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, SavedObjectsBulkGetObject, SavedObjectsBulkResolveObject, SavedObjectsBulkResponse, @@ -166,6 +168,13 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon return await this.options.baseClient.delete(type, id, options); } + public async bulkDelete( + objects: SavedObjectsBulkDeleteObject[], + options?: SavedObjectsBulkDeleteOptions + ) { + return await this.options.baseClient.bulkDelete(objects, options); + } + public async find(options: SavedObjectsFindOptions) { return await this.handleEncryptedAttributesInBulkResponse( await this.options.baseClient.find(options), diff --git a/x-pack/plugins/enterprise_search/common/types/connectors.ts b/x-pack/plugins/enterprise_search/common/types/connectors.ts index 655322e86f1b5..44105cf34c0c2 100644 --- a/x-pack/plugins/enterprise_search/common/types/connectors.ts +++ b/x-pack/plugins/enterprise_search/common/types/connectors.ts @@ -41,6 +41,7 @@ export interface IngestPipelineParams { export interface Connector { api_key_id: string | null; configuration: ConnectorConfiguration; + description: string | null; error: string | null; id: string; index_name: string; diff --git a/x-pack/plugins/enterprise_search/common/types/pipelines.ts b/x-pack/plugins/enterprise_search/common/types/pipelines.ts index 9438ce5ef4bc1..f6b3141cf9833 100644 --- a/x-pack/plugins/enterprise_search/common/types/pipelines.ts +++ b/x-pack/plugins/enterprise_search/common/types/pipelines.ts @@ -6,8 +6,8 @@ */ export interface InferencePipeline { + isDeployed: boolean; pipelineName: string; trainedModelName: string; - isDeployed: boolean; - modelType: string; + types: string[]; } diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx index f46454e45eb82..8d07e3aac6674 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx @@ -9,9 +9,9 @@ import '../../../__mocks__/shallow_useeffect.mock'; import React from 'react'; -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; -import { EuiCodeBlock } from '@elastic/eui'; +import { EuiCodeBlock, EuiDescriptionListDescription } from '@elastic/eui'; import { AnalyticsCollection } from '../../../../../common/types/analytics'; @@ -29,7 +29,18 @@ describe('AnalyticsCollectionIntegrate', () => { }); it('renders', () => { - const wrapper = shallow(); + const wrapper = mount(); expect(wrapper.find(EuiCodeBlock)).toHaveLength(2); + expect(wrapper.find(EuiDescriptionListDescription).get(0)).toMatchInlineSnapshot(` + + example + + `); + + expect(wrapper.find(EuiDescriptionListDescription).get(1)).toMatchInlineSnapshot(` + + /analytics/api/collections/example + + `); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx index ff5cdf9c5fee1..36b527097a304 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx @@ -28,7 +28,7 @@ interface AnalyticsCollectionIntegrateProps { export const AnalyticsCollectionIntegrate: React.FC = ({ collection, }) => { - const analyticsDNSUrl = getEnterpriseSearchUrl(`/analytics/${collection.name}`); + const analyticsDNSUrl = getEnterpriseSearchUrl(`/analytics/api/collections/${collection.name}`); const credentials = [ { title: i18n.translate( @@ -111,9 +111,9 @@ export const AnalyticsCollectionIntegrate: React.FC - {`window.elasticAnalytics.trackEvent("ResultClick", { + {`window.elasticAnalytics.trackEvent("click", { title: "Website Analytics", - url: "www.elasitc.co/analytics/website" + url: "www.elastic.co/analytics/overview" })`} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/search_indices.mock.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/search_indices.mock.ts index 457f37f5d13a9..b8063d57ff984 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/search_indices.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/search_indices.mock.ts @@ -27,6 +27,7 @@ export const indices: ElasticsearchIndexWithIngestion[] = [ connector: { api_key_id: null, configuration: { foo: { label: 'bar', value: 'barbar' } }, + description: null, error: null, id: '2', index_name: 'connector', @@ -76,6 +77,7 @@ export const indices: ElasticsearchIndexWithIngestion[] = [ connector: { api_key_id: null, configuration: { foo: { label: 'bar', value: 'barbar' } }, + description: null, error: null, id: '4', index_name: 'connector-crawler', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/view_index.mock.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/view_index.mock.ts index 52901d3e067c9..db4080f18e7a4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/view_index.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/view_index.mock.ts @@ -36,6 +36,7 @@ export const connectorIndex: ConnectorViewIndex = { connector: { api_key_id: null, configuration: { foo: { label: 'bar', value: 'barbar' } }, + description: null, error: null, id: '2', index_name: 'connector', @@ -91,6 +92,7 @@ export const connectorCrawlerIndex: CrawlerViewIndex = { connector: { api_key_id: null, configuration: { foo: { label: 'bar', value: 'barbar' } }, + description: null, error: null, id: '4', index_name: 'connector-crawler', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.ts new file mode 100644 index 0000000000000..caf19f80f040a --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_name_and_description_api_logic.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 { Connector } from '../../../../../common/types/connectors'; +import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export type PutConnectorNameAndDescriptionArgs = Partial< + Pick +> & { + connectorId: string; + indexName: string; +}; + +export type PutConnectorNameAndDescriptionResponse = Partial< + Pick +> & { + indexName: string; +}; + +export const putConnectorNameAndDescription = async ({ + connectorId, + description, + indexName, + name, +}: PutConnectorNameAndDescriptionArgs) => { + const route = `/internal/enterprise_search/connectors/${connectorId}/name_and_description`; + + await HttpLogic.values.http.put(route, { + body: JSON.stringify({ description, name }), + }); + return { description, indexName, name }; +}; + +export const ConnectorNameAndDescriptionApiLogic = createApiLogic( + ['content', 'connector_name_and_description_api_logic'], + putConnectorNameAndDescription +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/delete_ml_inference_pipeline.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/delete_ml_inference_pipeline.ts new file mode 100644 index 0000000000000..4abef52979380 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/delete_ml_inference_pipeline.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 { createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export interface DeleteMlInferencePipelineApiLogicArgs { + indexName: string; + pipelineName: string; +} + +export interface DeleteMlInferencePipelineResponse { + deleted?: string; + updated?: string; +} + +export const deleteMlInferencePipeline = async ( + args: DeleteMlInferencePipelineApiLogicArgs +): Promise => { + const route = `/internal/enterprise_search/indices/${args.indexName}/ml_inference/pipeline_processors/${args.pipelineName}`; + + return await HttpLogic.values.http.delete(route); +}; + +export const DeleteMlInferencePipelineApiLogic = createApiLogic( + ['delete_ml_inference_pipeline_api_logic'], + deleteMlInferencePipeline +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx index 47b5d565e62d4..cc97705d3f043 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx @@ -92,7 +92,19 @@ export const MethodConnector: React.FC<{ isNative: boolean }> = ({ isNative }) =

+ {i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.title', + { + defaultMessage: 'Build a connector', + } + )} + + ), + }} />

@@ -101,22 +113,13 @@ export const MethodConnector: React.FC<{ isNative: boolean }> = ({ isNative }) = title: i18n.translate( 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.nativeConnector.title', { - defaultMessage: 'Use a pre-built connector to populate your index', + defaultMessage: 'Configure a connector', } ), titleSize: 'xs', } : { - children: isNative ? ( - -

- -

-
- ) : ( + children: (

+ {TECHNICAL_PREVIEW_LABEL} + +); + const METHOD_BUTTON_GROUP_OPTIONS: ButtonGroupOption[] = [ { description: i18n.translate( 'xpack.enterpriseSearch.content.newIndex.buttonGroup.crawler.description', { - defaultMessage: 'Discover, extract, index, and sync of all your website content', + defaultMessage: 'Discover, extract, index, and sync all of your website content', } ), footer: i18n.translate('xpack.enterpriseSearch.content.newIndex.buttonGroup.crawler.footer', { @@ -57,10 +64,12 @@ const METHOD_BUTTON_GROUP_OPTIONS: ButtonGroupOption[] = [ }), }, { + badge: technicalPreviewBadge, description: i18n.translate( 'xpack.enterpriseSearch.content.newIndex.buttonGroup.nativeConnector.description', { - defaultMessage: 'Use our built-in connectors to connect to your data sources.', + defaultMessage: + 'Configure a connector to extract, index, and sync all of your content from supported data sources ', } ), footer: i18n.translate( @@ -95,11 +104,7 @@ const METHOD_BUTTON_GROUP_OPTIONS: ButtonGroupOption[] = [ }), }, { - badge: ( - - Technical Preview - - ), + badge: technicalPreviewBadge, description: i18n.translate( 'xpack.enterpriseSearch.content.newIndex.buttonGroup.connector.description', { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/api_total_stats.tsx similarity index 85% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/api_total_stats.tsx index dd55dd399392c..38f963d6fa1ce 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/api_total_stats.tsx @@ -15,13 +15,7 @@ import { i18n } from '@kbn/i18n'; import { OverviewLogic } from './overview.logic'; -interface TotalStatsProps { - additionalItems?: EuiStatProps[]; - ingestionType: string; - lastUpdated?: string; -} - -export const TotalStats: React.FC = ({ ingestionType, additionalItems = [] }) => { +export const ApiTotalStats: React.FC = () => { const { indexData, isError, isLoading } = useValues(OverviewLogic); const documentCount = indexData?.count ?? 0; const hideStats = isLoading || isError; @@ -35,7 +29,12 @@ export const TotalStats: React.FC = ({ ingestionType, additiona } ), isLoading: hideStats, - title: ingestionType, + title: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.apiIngestionMethodLabel', + { + defaultMessage: 'API', + } + ), }, { description: i18n.translate( @@ -47,7 +46,6 @@ export const TotalStats: React.FC = ({ ingestionType, additiona isLoading: hideStats, title: documentCount, }, - ...additionalItems, ]; return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx index 1ef66afa3106f..233825d6af135 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx @@ -43,6 +43,7 @@ import { SearchIndexTabId } from '../search_index'; import { ApiKeyConfig } from './api_key_configuration'; import { ConnectorConfigurationConfig } from './connector_configuration_config'; +import { ConnectorNameAndDescription } from './connector_name_and_description/connector_name_and_description'; import { NativeConnectorConfiguration } from './native_connector_configuration/native_connector_configuration'; export const ConnectorConfiguration: React.FC = () => { @@ -84,6 +85,17 @@ export const ConnectorConfiguration: React.FC = () => { ), titleSize: 'xs', }, + { + children: , + status: indexData.connector.description ? 'complete' : 'incomplete', + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.nameAndDescriptionTitle', + { + defaultMessage: 'Name and description', + } + ), + titleSize: 'xs', + }, { children: ( <> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description.tsx new file mode 100644 index 0000000000000..d75482e25e784 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useActions, useValues } from 'kea'; + +import { + EuiButton, + EuiDescriptionList, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, +} from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { NAME_LABEL, DESCRIPTION_LABEL, EDIT_BUTTON_LABEL } from '../../../../../shared/constants'; + +import { isConnectorIndex } from '../../../../utils/indices'; +import { IndexViewLogic } from '../../index_view_logic'; + +import { ConnectorNameAndDescriptionForm } from './connector_name_and_description_form'; +import { ConnectorNameAndDescriptionLogic } from './connector_name_and_description_logic'; + +export const ConnectorNameAndDescription: React.FC = () => { + const { index: indexData } = useValues(IndexViewLogic); + const { + isEditing, + nameAndDescription: { name, description }, + } = useValues(ConnectorNameAndDescriptionLogic); + const { setIsEditing } = useActions(ConnectorNameAndDescriptionLogic); + + if (!isConnectorIndex(indexData)) { + return <>; + } + + return ( + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescriptionForm.description', + { + defaultMessage: + 'By naming and describing this connector your colleagues and wider team will know what this connector is meant for.', + } + )} + + + + {isEditing ? ( + + ) : ( + <> + + + + + setIsEditing(!isEditing)}>{EDIT_BUTTON_LABEL} + + + + )} + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx new file mode 100644 index 0000000000000..33ea50ff8c6d6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useActions, useValues } from 'kea'; + +import { + EuiButton, + EuiButtonEmpty, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiTextArea, +} from '@elastic/eui'; + +import { Status } from '../../../../../../../common/types/api'; +import { + NAME_LABEL, + DESCRIPTION_LABEL, + SAVE_BUTTON_LABEL, + CANCEL_BUTTON_LABEL, +} from '../../../../../shared/constants'; +import { ConnectorNameAndDescriptionApiLogic } from '../../../../api/connector/update_connector_name_and_description_api_logic'; +import { isConnectorIndex } from '../../../../utils/indices'; +import { IndexViewLogic } from '../../index_view_logic'; + +import { ConnectorNameAndDescriptionLogic } from './connector_name_and_description_logic'; + +export const ConnectorNameAndDescriptionForm: React.FC = () => { + const { index: indexData } = useValues(IndexViewLogic); + const { status } = useValues(ConnectorNameAndDescriptionApiLogic); + const { + localNameAndDescription: { name, description }, + } = useValues(ConnectorNameAndDescriptionLogic); + const { saveNameAndDescription, setIsEditing, updateLocalNameAndDescription } = useActions( + ConnectorNameAndDescriptionLogic + ); + + if (!isConnectorIndex(indexData)) { + return <>; + } + + return ( + { + event.preventDefault(); + saveNameAndDescription(); + }} + component="form" + > + + { + updateLocalNameAndDescription({ name: event.target.value }); + }} + /> + + + { + updateLocalNameAndDescription({ description: event.target.value }); + }} + /> + + + + + + {SAVE_BUTTON_LABEL} + + + + { + setIsEditing(false); + }} + > + {CANCEL_BUTTON_LABEL} + + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts new file mode 100644 index 0000000000000..a18b71320ca0b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_logic.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { i18n } from '@kbn/i18n'; + +import { Connector } from '../../../../../../../common/types/connectors'; +import { Actions } from '../../../../../shared/api_logic/create_api_logic'; +import { + flashAPIErrors, + flashSuccessToast, + clearFlashMessages, +} from '../../../../../shared/flash_messages'; +import { + ConnectorNameAndDescriptionApiLogic, + PutConnectorNameAndDescriptionArgs, + PutConnectorNameAndDescriptionResponse, +} from '../../../../api/connector/update_connector_name_and_description_api_logic'; +import { + FetchIndexApiLogic, + FetchIndexApiParams, + FetchIndexApiResponse, +} from '../../../../api/index/fetch_index_api_logic'; +import { isConnectorIndex } from '../../../../utils/indices'; + +type NameAndDescription = Partial>; + +type ConnectorNameAndDescriptionActions = Pick< + Actions, + 'apiError' | 'apiSuccess' | 'makeRequest' +> & { + fetchIndexApiSuccess: Actions['apiSuccess']; + saveNameAndDescription: () => void; + setIsEditing(isEditing: boolean): { isEditing: boolean }; + setLocalNameAndDescription(nameAndDescription: NameAndDescription): NameAndDescription; + setNameAndDescription(nameAndDescription: NameAndDescription): NameAndDescription; + updateLocalNameAndDescription(nameAndDescription: NameAndDescription): NameAndDescription; +}; + +interface ConnectorNameAndDescriptionValues { + index: FetchIndexApiResponse; + isEditing: boolean; + localNameAndDescription: NameAndDescription; + nameAndDescription: NameAndDescription; +} + +export const ConnectorNameAndDescriptionLogic = kea< + MakeLogicType +>({ + actions: { + saveNameAndDescription: true, + setIsEditing: (isEditing: boolean) => ({ + isEditing, + }), + setLocalNameAndDescription: (nameAndDescription) => nameAndDescription, + setNameAndDescription: (nameAndDescription) => nameAndDescription, + updateLocalNameAndDescription: (nameAndDescription) => nameAndDescription, + }, + connect: { + actions: [ + ConnectorNameAndDescriptionApiLogic, + ['apiError', 'apiSuccess', 'makeRequest'], + FetchIndexApiLogic, + ['apiSuccess as fetchIndexApiSuccess'], + ], + values: [FetchIndexApiLogic, ['data as index']], + }, + events: ({ actions, values }) => ({ + afterMount: () => + actions.setNameAndDescription(isConnectorIndex(values.index) ? values.index.connector : {}), + }), + listeners: ({ actions, values }) => ({ + apiError: (error) => flashAPIErrors(error), + apiSuccess: ({ indexName }) => { + flashSuccessToast( + i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.configuration.successToast.title', + { defaultMessage: 'Configuration successfully updated' } + ) + ); + FetchIndexApiLogic.actions.makeRequest({ indexName }); + }, + fetchIndexApiSuccess: (index) => { + if (!values.isEditing && isConnectorIndex(index)) { + actions.setNameAndDescription(index.connector); + } + }, + makeRequest: () => clearFlashMessages(), + saveNameAndDescription: () => { + if (isConnectorIndex(values.index)) { + actions.makeRequest({ + connectorId: values.index.connector.id, + indexName: values.index.connector.index_name, + ...values.localNameAndDescription, + }); + } + }, + setIsEditing: (isEditing) => { + if (isEditing) { + actions.setLocalNameAndDescription(values.nameAndDescription); + } + }, + }), + path: ['enterprise_search', 'content', 'connector_name_and_description'], + reducers: () => ({ + isEditing: [ + false, + { + apiSuccess: () => false, + setIsEditing: (_, { isEditing }) => isEditing, + }, + ], + localNameAndDescription: [ + {}, + { + setLocalNameAndDescription: (_, nameAndDescription) => nameAndDescription, + updateLocalNameAndDescription: (localNameAndDescription, nameAndDescription) => ({ + ...localNameAndDescription, + ...nameAndDescription, + }), + }, + ], + nameAndDescription: [ + {}, + { + apiSuccess: (_, { description, name }) => ({ description, name }), + setNameAndDescription: (_, nameAndDescription) => nameAndDescription, + }, + ], + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_overview_panels.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_overview_panels.tsx index a0d1c3d97fe96..78152d64d248b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_overview_panels.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_overview_panels.tsx @@ -28,8 +28,6 @@ import { import { IndexViewLogic } from '../index_view_logic'; import { SearchIndexTabId } from '../search_index'; -import { NATIVE_CONNECTORS } from './constants'; - const StatusPanel: React.FC<{ ingestionStatus: IngestionStatus }> = ({ ingestionStatus }) => ( { return isConnectorIndex(index) ? ( - - - - - - + connector.serviceType === index.connector.service_type - )?.name ?? - index.connector.service_type ?? - i18n.translate('xpack.enterpriseSearch.connector.connectorTypePanel.unknown.label', { - defaultMessage: 'Unknown', - }) - } + title={index.count} /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/connector_name_and_description.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/connector_name_and_description.tsx deleted file mode 100644 index 552d0ce197c87..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/connector_name_and_description.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { useValues } from 'kea'; - -import { - EuiButton, - EuiFieldText, - EuiFlexGroup, - EuiFlexItem, - EuiForm, - EuiFormRow, - EuiText, - EuiTextArea, -} from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; - -import { isConnectorIndex } from '../../../../utils/indices'; -import { IndexViewLogic } from '../../index_view_logic'; -import { NativeConnector } from '../types'; - -interface ConnectorNameAndDescriptionProps { - nativeConnector: NativeConnector; -} - -export const ConnectorNameAndDescription: React.FC = ({ - nativeConnector, -}) => { - const { index: indexData } = useValues(IndexViewLogic); - const { name } = nativeConnector; - return ( - - - - - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescriptionForm.description', - { - defaultMessage: - 'By naming and describing this connector your colleagues and wider team will know what this connector is meant for.', - } - )} - - - - - - - - - - - - - - - - - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescriptionForm.submitButtonLabel', - { - defaultMessage: 'Save name and description', - } - )} - - - - - - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_configuration.tsx index aaa85de188985..18aa5a43582b7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_configuration.tsx @@ -28,6 +28,7 @@ import { NATIVE_CONNECTOR_ICONS } from '../../../../../../assets/source_icons/na import { hasConfiguredConfiguration } from '../../../../utils/has_configured_configuration'; import { isConnectorIndex } from '../../../../utils/indices'; import { IndexViewLogic } from '../../index_view_logic'; +import { ConnectorNameAndDescription } from '../connector_name_and_description/connector_name_and_description'; import { NATIVE_CONNECTORS } from '../constants'; import { NativeConnectorAdvancedConfiguration } from './native_connector_advanced_configuration'; @@ -49,10 +50,11 @@ export const NativeConnectorConfiguration: React.FC = () => { return <>; } + const hasDescription = !!indexData.connector.description; const hasConfigured = hasConfiguredConfiguration(indexData.connector.configuration); const hasConfiguredAdvanced = indexData.connector.last_synced || indexData.connector.scheduling.enabled; - const hasResearched = hasConfigured || hasConfiguredAdvanced; + const hasResearched = hasDescription || hasConfigured || hasConfiguredAdvanced; const icon = NATIVE_CONNECTOR_ICONS[nativeConnector.serviceType]; return ( @@ -87,18 +89,17 @@ export const NativeConnectorConfiguration: React.FC = () => { ), titleSize: 'xs', }, - /* Commenting this out for a future PR to implement fully */ - // { - // children: , - // status: hasName ? 'complete' : 'incomplete', - // title: i18n.translate( - // 'xpack.enterpriseSearch.content.indices.configurationConnector.nativeConnector.steps.nameAndDescriptionTitle', - // { - // defaultMessage: 'Name and description', - // } - // ), - // titleSize: 'xs', - // }, + { + children: , + status: hasDescription ? 'complete' : 'incomplete', + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.nativeConnector.steps.nameAndDescriptionTitle', + { + defaultMessage: 'Name and description', + } + ), + titleSize: 'xs', + }, { children: ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector_total_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector_total_stats.tsx new file mode 100644 index 0000000000000..2b5ef4cb68df7 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector_total_stats.tsx @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { + EuiStatProps, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiStat, + EuiSpacer, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { isConnectorIndex } from '../../utils/indices'; + +import { ConnectorOverviewPanels } from './connector/connector_overview_panels'; +import { NATIVE_CONNECTORS } from './connector/constants'; +import { NameAndDescriptionStats } from './name_and_description_stats'; +import { OverviewLogic } from './overview.logic'; + +export const ConnectorTotalStats: React.FC = () => { + const { indexData, isError, isLoading } = useValues(OverviewLogic); + const hideStats = isLoading || isError; + + if (!isConnectorIndex(indexData)) { + return <>; + } + + const stats: EuiStatProps[] = [ + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.ingestionTypeCardLabel', + { + defaultMessage: 'Ingestion type', + } + ), + isLoading: hideStats, + title: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.connectorIngestionMethodLabel', + { + defaultMessage: 'Connector', + } + ), + }, + { + description: i18n.translate('xpack.enterpriseSearch.connector.connectorTypePanel.title', { + defaultMessage: 'Connector type', + }), + title: + NATIVE_CONNECTORS.find( + (connector) => connector.serviceType === indexData.connector.service_type + )?.name ?? + indexData.connector.service_type ?? + i18n.translate('xpack.enterpriseSearch.connector.connectorTypePanel.unknown.label', { + defaultMessage: 'Unknown', + }), + }, + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.languageLabel', + { + defaultMessage: 'Language analyzer', + } + ), + isLoading: hideStats, + title: + indexData.connector.language ?? + i18n.translate('xpack.enterpriseSearch.content.searchIndex.totalStats.noneLabel', { + defaultMessage: 'None', + }), + }, + ]; + + return ( + <> + + + + {stats.map((item, index) => ( + + + + + + ))} + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx index 367932d987900..f396dd19d5385 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx @@ -9,15 +9,34 @@ import React from 'react'; import { useValues } from 'kea'; +import { EuiStatProps, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { CrawlerLogic } from './crawler/crawler_logic'; -import { TotalStats } from './total_stats'; +import { OverviewLogic } from './overview.logic'; export const CrawlerTotalStats: React.FC = () => { const { domains, dataLoading } = useValues(CrawlerLogic); + const { indexData, isError, isLoading } = useValues(OverviewLogic); + const documentCount = indexData?.count ?? 0; + const hideStats = isLoading || isError; - const additionalItems = [ + const stats: EuiStatProps[] = [ + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.ingestionTypeCardLabel', + { + defaultMessage: 'Ingestion type', + } + ), + isLoading: hideStats, + title: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.crawlerIngestionMethodLabel', + { + defaultMessage: 'Crawler', + } + ), + }, { description: i18n.translate( 'xpack.enterpriseSearch.content.searchIndex.totalStats.domainCountCardLabel', @@ -25,20 +44,30 @@ export const CrawlerTotalStats: React.FC = () => { defaultMessage: 'Domain count', } ), - isLoading: dataLoading, + isLoading: dataLoading || hideStats, title: domains.length, }, + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.documentCountCardLabel', + { + defaultMessage: 'Document count', + } + ), + isLoading: hideStats, + title: documentCount, + }, ]; return ( - + + {stats.map((item, index) => ( + + + + + + ))} + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx new file mode 100644 index 0000000000000..a7f150d24cbf2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat, EuiStatProps, EuiText } from '@elastic/eui'; + +import { DESCRIPTION_LABEL, NAME_LABEL } from '../../../shared/constants'; +import { generateEncodedPath } from '../../../shared/encode_path_params'; +import { EuiLinkTo } from '../../../shared/react_router_helpers'; +import { SEARCH_INDEX_TAB_PATH } from '../../routes'; +import { isConnectorIndex } from '../../utils/indices'; + +import { IndexNameLogic } from './index_name_logic'; +import { OverviewLogic } from './overview.logic'; +import { SearchIndexTabId } from './search_index'; + +const EditDescription: React.FC<{ label: string; indexName: string }> = ({ label, indexName }) => ( + + {label} + + + Edit + + + +); + +export const NameAndDescriptionStats: React.FC = () => { + const { indexName } = useValues(IndexNameLogic); + const { indexData, isError, isLoading } = useValues(OverviewLogic); + const hideStats = isLoading || isError; + + if (!isConnectorIndex(indexData)) { + return <>; + } + + const stats: EuiStatProps[] = [ + { + description: , + isLoading: hideStats, + title: indexData.connector.name, + }, + { + description: , + isLoading: hideStats, + title: {indexData.connector.description || ''}, + titleElement: 'p', + }, + ]; + + return ( + + {stats.map((item, index) => ( + + + + + + ))} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx index f30c9a24dda92..56ec6a7563dec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx @@ -15,14 +15,14 @@ import { i18n } from '@kbn/i18n'; import { isApiIndex, isConnectorIndex, isCrawlerIndex } from '../../utils/indices'; -import { ConnectorOverviewPanels } from './connector/connector_overview_panels'; +import { ApiTotalStats } from './api_total_stats'; +import { ConnectorTotalStats } from './connector_total_stats'; import { CrawlDetailsFlyout } from './crawler/crawl_details_flyout/crawl_details_flyout'; import { CrawlRequestsPanel } from './crawler/crawl_requests_panel/crawl_requests_panel'; import { CrawlerTotalStats } from './crawler_total_stats'; import { GenerateApiKeyPanel } from './generate_api_key_panel'; import { OverviewLogic } from './overview.logic'; import { SyncJobs } from './sync_jobs'; -import { TotalStats } from './total_stats'; export const SearchIndexOverview: React.FC = () => { const { indexData } = useValues(OverviewLogic); @@ -50,24 +50,10 @@ export const SearchIndexOverview: React.FC = () => { )} {isCrawlerIndex(indexData) ? ( + ) : isConnectorIndex(indexData) ? ( + ) : ( - + )} {isApiIndex(indexData) && ( <> @@ -84,8 +70,6 @@ export const SearchIndexOverview: React.FC = () => { )} {isConnectorIndex(indexData) && ( <> - - diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx index fab7620f7f232..1c79cff0244e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx @@ -16,15 +16,15 @@ import { EuiBadge, EuiHealth, EuiPanel, EuiTitle } from '@elastic/eui'; import { InferencePipelineCard } from './inference_pipeline_card'; export const DEFAULT_VALUES = { + isDeployed: true, pipelineName: 'Sample Processor', trainedModelName: 'example_trained_model', - isDeployed: true, - modelType: 'pytorch', + types: ['pytorch'], }; const mockValues = { ...DEFAULT_VALUES }; -describe('InfererencePipelineCard', () => { +describe('InferencePipelineCard', () => { beforeEach(() => { jest.clearAllMocks(); setMockValues(mockValues); @@ -38,10 +38,4 @@ describe('InfererencePipelineCard', () => { const health = wrapper.find(EuiHealth); expect(health.prop('children')).toEqual('Deployed'); }); - - it('renders an undeployed item', () => { - const wrapper = shallow(); - const health = wrapper.find(EuiHealth); - expect(health.prop('children')).toEqual('Not deployed'); - }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx index 50a8082322817..e67cbdd9005c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx @@ -7,17 +7,19 @@ import React, { useState } from 'react'; -import { useValues } from 'kea'; +import { useActions, useValues } from 'kea'; import { EuiBadge, EuiButtonEmpty, + EuiConfirmModal, EuiFlexGroup, EuiFlexItem, EuiHealth, EuiPanel, EuiPopover, EuiPopoverTitle, + EuiText, EuiTextColor, EuiTitle, } from '@elastic/eui'; @@ -25,26 +27,28 @@ import { import { i18n } from '@kbn/i18n'; import { InferencePipeline } from '../../../../../../common/types/pipelines'; +import { CANCEL_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../../../../shared/constants'; import { HttpLogic } from '../../../../shared/http'; +import { IndexNameLogic } from '../index_name_logic'; + +import { PipelinesLogic } from './pipelines_logic'; export const InferencePipelineCard: React.FC = ({ pipelineName, trainedModelName, isDeployed, - modelType, + types, }) => { const { http } = useValues(HttpLogic); + const { indexName } = useValues(IndexNameLogic); const [isPopOverOpen, setIsPopOverOpen] = useState(false); + const [showConfirmDelete, setShowConfirmDelete] = useState(false); + const { deleteMlPipeline } = useActions(PipelinesLogic); const deployedText = i18n.translate('xpack.enterpriseSearch.inferencePipelineCard.isDeployed', { defaultMessage: 'Deployed', }); - const notDeployedText = i18n.translate( - 'xpack.enterpriseSearch.inferencePipelineCard.isNotDeployed', - { defaultMessage: 'Not deployed' } - ); - const actionButton = ( = ({

- + setShowConfirmDelete(true)} + > {i18n.translate( 'xpack.enterpriseSearch.inferencePipelineCard.action.delete', { defaultMessage: 'Delete pipeline' } @@ -120,23 +130,61 @@ export const InferencePipelineCard: React.FC = ({ - - - {isDeployed ? deployedText : notDeployedText} - - - - - - {modelType} - - - + {isDeployed && ( + + {deployedText} + + )} + {types.map((type) => ( + + + + {type} + + + + ))} + {showConfirmDelete && ( + setShowConfirmDelete(false)} + onConfirm={() => { + setShowConfirmDelete(false); + deleteMlPipeline({ + indexName, + pipelineName, + }); + }} + title={i18n.translate( + 'xpack.enterpriseSearch.inferencePipelineCard.deleteConfirm.title', + { defaultMessage: 'Delete Pipeline' } + )} + buttonColor="danger" + cancelButtonText={CANCEL_BUTTON_LABEL} + confirmButtonText={DELETE_BUTTON_LABEL} + defaultFocusedButton="confirm" + maxWidth + > + +

+ {i18n.translate( + 'xpack.enterpriseSearch.inferencePipelineCard.deleteConfirm.description', + { + defaultMessage: + 'You are removing the pipeline "{pipelineName}" from the Machine Learning Inference Pipeline and deleting it.', + values: { + pipelineName, + }, + } + )} +

+
+
+ )} ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx index 0b8d7ec671753..ab90aa1d85464 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx @@ -36,7 +36,7 @@ export const MlInferencePipelineProcessorsCard: React.FC = () => { trainedModelName={item.trainedModelName} pipelineName={item.pipelineName} isDeployed={item.isDeployed} - modelType={item.modelType} + types={item.types} /> ))} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts index 290b4e469764f..e6cb840be420a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts @@ -47,6 +47,11 @@ import { FetchIndexApiResponse, } from '../../../api/index/fetch_index_api_logic'; import { CreateMlInferencePipelineApiLogic } from '../../../api/ml_models/create_ml_inference_pipeline'; +import { + DeleteMlInferencePipelineApiLogic, + DeleteMlInferencePipelineApiLogicArgs, + DeleteMlInferencePipelineResponse, +} from '../../../api/ml_models/delete_ml_inference_pipeline'; import { FetchMlInferencePipelineProcessorsApiLogic } from '../../../api/pipelines/fetch_ml_inference_pipeline_processors'; import { isApiIndex, isConnectorIndex, isCrawlerIndex } from '../../../utils/indices'; @@ -54,8 +59,8 @@ type PipelinesActions = Pick< Actions, 'apiError' | 'apiSuccess' | 'makeRequest' > & { - closeModal: () => void; closeAddMlInferencePipelineModal: () => void; + closeModal: () => void; createCustomPipeline: Actions< CreateCustomPipelineApiLogicArgs, CreateCustomPipelineApiLogicResponse @@ -68,6 +73,18 @@ type PipelinesActions = Pick< CreateCustomPipelineApiLogicArgs, CreateCustomPipelineApiLogicResponse >['apiSuccess']; + deleteMlPipeline: Actions< + DeleteMlInferencePipelineApiLogicArgs, + DeleteMlInferencePipelineResponse + >['makeRequest']; + deleteMlPipelineError: Actions< + DeleteMlInferencePipelineApiLogicArgs, + DeleteMlInferencePipelineResponse + >['apiError']; + deleteMlPipelineSuccess: Actions< + DeleteMlInferencePipelineApiLogicArgs, + DeleteMlInferencePipelineResponse + >['apiSuccess']; fetchCustomPipeline: Actions< FetchCustomPipelineApiLogicArgs, FetchCustomPipelineApiLogicResponse @@ -77,12 +94,12 @@ type PipelinesActions = Pick< fetchIndexApiSuccess: Actions['apiSuccess']; fetchMlInferenceProcessors: typeof FetchMlInferencePipelineProcessorsApiLogic.actions.makeRequest; fetchMlInferenceProcessorsApiError: (error: HttpError) => HttpError; + openAddMlInferencePipelineModal: () => void; openModal: () => void; savePipeline: () => void; setPipelineState(pipeline: IngestPipelineParams): { pipeline: IngestPipelineParams; }; - openAddMlInferencePipelineModal: () => void; }; interface PipelinesValues { @@ -93,16 +110,16 @@ interface PipelinesValues { index: FetchIndexApiResponse; mlInferencePipelineProcessors: InferencePipeline[]; pipelineState: IngestPipelineParams; - showModal: boolean; showAddMlInferencePipelineModal: boolean; + showModal: boolean; } export const PipelinesLogic = kea>({ actions: { - closeModal: true, closeAddMlInferencePipelineModal: true, - openModal: true, + closeModal: true, openAddMlInferencePipelineModal: true, + openModal: true, savePipeline: true, setPipelineState: (pipeline: IngestPipelineParams) => ({ pipeline }), }, @@ -129,6 +146,12 @@ export const PipelinesLogic = kea { actions.fetchMlInferenceProcessors({ indexName: values.index.name }); }, + deleteMlPipelineError: (error) => flashAPIErrors(error), + deleteMlPipelineSuccess: (value) => { + if (value.deleted) { + flashSuccessToast( + i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.successToastDeleteMlPipeline.title', + { + defaultMessage: 'Deleted machine learning inference pipeline "{pipelineName}"', + values: { + pipelineName: value.deleted, + }, + } + ) + ); + } + actions.fetchMlInferenceProcessors({ indexName: values.index.name }); + }, fetchIndexApiSuccess: (index) => { if (!values.showModal) { // Don't do this when the modal is open to avoid overwriting the values while editing @@ -227,20 +267,20 @@ export const PipelinesLogic = kea pipeline, }, ], - showModal: [ + showAddMlInferencePipelineModal: [ false, { - apiSuccess: () => false, - closeModal: () => false, - openModal: () => true, + closeAddMlInferencePipelineModal: () => false, + createMlInferencePipelineSuccess: () => false, + openAddMlInferencePipelineModal: () => true, }, ], - showAddMlInferencePipelineModal: [ + showModal: [ false, { - createMlInferencePipelineSuccess: () => false, - closeAddMlInferencePipelineModal: () => false, - openAddMlInferencePipelineModal: () => true, + apiSuccess: () => false, + closeModal: () => false, + openModal: () => true, }, ], }), diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/constants/labels.ts b/x-pack/plugins/enterprise_search/public/applications/shared/constants/labels.ts index 88cec898afcb0..fa982547f7fc5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/constants/labels.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/constants/labels.ts @@ -26,3 +26,18 @@ export const TYPE_LABEL = i18n.translate('xpack.enterpriseSearch.typeLabel', { export const EMAIL_LABEL = i18n.translate('xpack.enterpriseSearch.emailLabel', { defaultMessage: 'Email', }); + +export const TECHNICAL_PREVIEW_LABEL = i18n.translate( + 'xpack.enterpriseSearch.technicalPreviewLabel', + { + defaultMessage: 'Technical Preview', // title case specifically requested + } +); + +export const NAME_LABEL = i18n.translate('xpack.enterpriseSearch.nameLabel', { + defaultMessage: 'Name', +}); + +export const DESCRIPTION_LABEL = i18n.translate('xpack.enterpriseSearch.descriptionLabel', { + defaultMessage: 'Description', +}); diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index 6dff94d411597..ac7581814242e 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -15,6 +15,7 @@ import { Plugin, PluginInitializerContext, DEFAULT_APP_CATEGORIES, + AppNavLinkStatus, } from '@kbn/core/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; @@ -125,6 +126,9 @@ export class EnterpriseSearchPlugin implements Plugin { title: ANALYTICS_PLUGIN.NAME, euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, searchable: bahavioralAnalyticsEnabled, + navLinkStatus: bahavioralAnalyticsEnabled + ? AppNavLinkStatus.default + : AppNavLinkStatus.hidden, appRoute: ANALYTICS_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, mount: async (params: AppMountParameters) => { diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts index d8a0ace2603dd..cad0b3b88e38e 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts @@ -86,6 +86,7 @@ describe('addConnector lib function', () => { document: { api_key_id: null, configuration: {}, + description: null, error: null, index_name: 'index_name', is_native: false, @@ -216,6 +217,7 @@ describe('addConnector lib function', () => { document: { api_key_id: null, configuration: {}, + description: null, error: null, index_name: 'index_name', is_native: true, @@ -268,6 +270,7 @@ describe('addConnector lib function', () => { document: { api_key_id: null, configuration: {}, + description: null, error: null, index_name: 'search-index_name', is_native: false, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts index 63c4d1834c4f4..1b02dda8d26ad 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts @@ -87,6 +87,7 @@ export const addConnector = async ( const document: ConnectorDocument = { api_key_id: null, configuration: {}, + description: null, error: null, index_name: input.index_name, is_native: input.is_native, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_name_and_description.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_name_and_description.ts new file mode 100644 index 0000000000000..caca94ee2713a --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_name_and_description.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IScopedClusterClient } from '@kbn/core/server'; +import { i18n } from '@kbn/i18n'; + +import { CONNECTORS_INDEX } from '../..'; + +import { Connector, ConnectorDocument } from '../../../common/types/connectors'; + +export const updateConnectorNameAndDescription = async ( + client: IScopedClusterClient, + connectorId: string, + connectorUpdates: Partial> +) => { + const connectorResult = await client.asCurrentUser.get({ + id: connectorId, + index: CONNECTORS_INDEX, + }); + const connector = connectorResult._source; + if (connector) { + const result = await client.asCurrentUser.index({ + document: { ...connector, ...connectorUpdates }, + id: connectorId, + index: CONNECTORS_INDEX, + }); + await client.asCurrentUser.indices.refresh({ index: CONNECTORS_INDEX }); + return result; + } else { + throw new Error( + i18n.translate('xpack.enterpriseSearch.server.connectors.serviceType.error', { + defaultMessage: 'Could not find document', + }) + ); + } +}; diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/delete_ml_inference_pipeline.ts b/x-pack/plugins/enterprise_search/server/lib/indices/delete_ml_inference_pipeline.ts index 282487e62f023..04a032e3be102 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/delete_ml_inference_pipeline.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/delete_ml_inference_pipeline.ts @@ -8,6 +8,8 @@ import { IngestPutPipelineRequest } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core/server'; +import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; + /** * Response for deleting sub-pipeline from @ml-inference pipeline. * If sub-pipeline was deleted successfully, 'deleted' field contains its name. @@ -24,7 +26,7 @@ export const deleteMlInferencePipeline = async ( client: ElasticsearchClient ) => { const response: DeleteMlInferencePipelineResponse = {}; - const parentPipelineId = `${indexName}@ml-inference`; + const parentPipelineId = getInferencePipelineNameFromIndexName(indexName); // find parent pipeline try { diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts index 35bdbe0d64064..eb923a8f29852 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts @@ -42,8 +42,8 @@ const mockGetPipeline2 = { }, { inference: { - model_id: 'trained-model-id-1', inference_config: { regression: {} }, + model_id: 'trained-model-id-1', }, }, ], @@ -53,8 +53,8 @@ const mockGetPipeline2 = { processors: [ { inference: { - model_id: 'trained-model-id-2', inference_config: { regression: {} }, + model_id: 'trained-model-id-2', }, }, ], @@ -75,12 +75,16 @@ const mockGetTrainedModelsData = { count: 1, trained_model_configs: [ { + inference_config: { ner: {} }, model_id: 'trained-model-id-1', model_type: 'lang_ident', + tags: [], }, { + inference_config: { ner: {} }, model_id: 'trained-model-id-2', model_type: 'pytorch', + tags: [], }, ], }; @@ -92,26 +96,26 @@ const mockGetTrainedModelStats = { model_id: 'trained-model-id-1', }, { - model_id: 'trained-model-id-2', deployment_stats: { state: 'started', }, + model_id: 'trained-model-id-2', }, ], }; -const something = { +const trainedModelDataObject = { 'trained-model-id-1': { isDeployed: false, - modelType: 'lang_ident', pipelineName: 'ml-inference-pipeline-1', trainedModelName: 'trained-model-id-1', + types: ['lang_ident', 'ner'], }, 'trained-model-id-2': { isDeployed: true, - modelType: 'pytorch', pipelineName: 'ml-inference-pipeline-2', trainedModelName: 'trained-model-id-2', + types: ['pytorch', 'ner'], }, }; @@ -172,15 +176,15 @@ describe('fetchPipelineProcessorInferenceData lib function', () => { const expected = { 'trained-model-id-1': { isDeployed: false, - modelType: 'unknown', pipelineName: 'ml-inference-pipeline-1', trainedModelName: 'trained-model-id-1', + types: [], }, 'trained-model-id-2': { isDeployed: false, - modelType: 'unknown', pipelineName: 'ml-inference-pipeline-2', trainedModelName: 'trained-model-id-2', + types: [], }, }; @@ -219,19 +223,19 @@ describe('fetchAndAddTrainedModelData lib function', () => { const input = { 'trained-model-id-1': { isDeployed: false, - modelType: 'unknown', pipelineName: 'ml-inference-pipeline-1', trainedModelName: 'trained-model-id-1', + types: [], }, 'trained-model-id-2': { isDeployed: false, - modelType: 'unknown', pipelineName: 'ml-inference-pipeline-2', trainedModelName: 'trained-model-id-2', + types: [], }, } as Record; - const expected = something as Record; + const expected = trainedModelDataObject as Record; const response = await fetchAndAddTrainedModelData( mockClient as unknown as ElasticsearchClient, @@ -311,7 +315,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { }); describe('when using an index that has an ml-inference pipeline', () => { - it('should return an empty array', async () => { + it('should return pipeline processor data for that pipeline', async () => { mockClient.ingest.getPipeline.mockImplementationOnce(() => Promise.resolve(mockGetPipeline)); mockClient.ingest.getPipeline.mockImplementationOnce(() => Promise.resolve({ 'ml-inference-pipeline-1': mockGetPipeline2['ml-inference-pipeline-1'] }) @@ -323,7 +327,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { Promise.resolve(mockGetTrainedModelStats) ); - const expected = [something['trained-model-id-1']]; + const expected = [trainedModelDataObject['trained-model-id-1']] as InferencePipeline[]; const response = await fetchMlInferencePipelineProcessors( mockClient as unknown as ElasticsearchClient, diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts index 2a4a90dcfacfd..cfc80fc0f8b8b 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts @@ -6,15 +6,17 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; +import { BUILT_IN_MODEL_TAG } from '@kbn/ml-plugin/common/constants/data_frame_analytics'; import { InferencePipeline } from '../../../common/types/pipelines'; +import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; export const fetchMlInferencePipelineProcessorNames = async ( client: ElasticsearchClient, indexName: string ): Promise => { try { - const mlInferencePipelineName = `${indexName}@ml-inference`; + const mlInferencePipelineName = getInferencePipelineNameFromIndexName(indexName); const { [mlInferencePipelineName]: { processors: mlInferencePipelineProcessors = [] }, } = await client.ingest.getPipeline({ @@ -52,9 +54,9 @@ export const fetchPipelineProcessorInferenceData = async ( if (trainedModelName) pipelineProcessorData[trainedModelName] = { isDeployed: false, - modelType: 'unknown', pipelineName: pipelineProcessorName, trainedModelName, + types: [], }; return pipelineProcessorData; @@ -78,7 +80,13 @@ export const fetchAndAddTrainedModelData = async ( const trainedModelName = trainedModelData.model_id; if (pipelineProcessorData.hasOwnProperty(trainedModelName)) { - pipelineProcessorData[trainedModelName].modelType = trainedModelData.model_type || 'unknown'; + const isBuiltIn = trainedModelData.tags.includes(BUILT_IN_MODEL_TAG); + + pipelineProcessorData[trainedModelName].types = [ + trainedModelData.model_type, + ...Object.keys(trainedModelData.inference_config || {}), + ...(isBuiltIn ? [BUILT_IN_MODEL_TAG] : []), + ].filter((type): type is string => type !== undefined); } }); diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts index 974d00fb6ae1d..6f9a5f0fdc5fb 100644 --- a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts @@ -7,6 +7,8 @@ import { ElasticsearchClient } from '@kbn/core/server'; +import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; + import { createIndexPipelineDefinitions } from './create_pipeline_definitions'; import { formatMlPipelineBody } from './create_pipeline_definitions'; @@ -20,7 +22,7 @@ describe('createIndexPipelineDefinitions util function', () => { }; const expectedResult = { - created: [indexName, `${indexName}@custom`, `${indexName}@ml-inference`], + created: [indexName, `${indexName}@custom`, getInferencePipelineNameFromIndexName(indexName)], }; beforeEach(() => { diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts index 2099f6bfc070f..4389ab8659af7 100644 --- a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts @@ -8,6 +8,8 @@ import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core/server'; +import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; + export interface CreatedPipelines { created: string[]; } @@ -35,7 +37,7 @@ export const createIndexPipelineDefinitions = ( // TODO: add back descriptions (see: https://github.com/elastic/elasticsearch-specification/issues/1827) esClient.ingest.putPipeline({ description: `Enterprise Search Machine Learning Inference pipeline for the '${indexName}' index`, - id: `${indexName}@ml-inference`, + id: getInferencePipelineNameFromIndexName(indexName), processors: [], version: 1, }); @@ -97,7 +99,7 @@ export const createIndexPipelineDefinitions = ( { pipeline: { if: 'ctx?._run_ml_inference == true', - name: `${indexName}@ml-inference`, + name: getInferencePipelineNameFromIndexName(indexName), on_failure: [ { append: { @@ -228,7 +230,9 @@ export const createIndexPipelineDefinitions = ( ], version: 1, }); - return { created: [indexName, `${indexName}@custom`, `${indexName}@ml-inference`] }; + return { + created: [indexName, `${indexName}@custom`, getInferencePipelineNameFromIndexName(indexName)], + }; }; /** diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts index 6c61e62ce0c66..c0dcc2dbdb0a9 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts @@ -16,6 +16,7 @@ import { addConnector } from '../../lib/connectors/add_connector'; import { fetchSyncJobsByConnectorId } from '../../lib/connectors/fetch_sync_jobs'; import { startConnectorSync } from '../../lib/connectors/start_sync'; import { updateConnectorConfiguration } from '../../lib/connectors/update_connector_configuration'; +import { updateConnectorNameAndDescription } from '../../lib/connectors/update_connector_name_and_description'; import { updateConnectorScheduling } from '../../lib/connectors/update_connector_scheduling'; import { updateConnectorServiceType } from '../../lib/connectors/update_connector_service_type'; import { updateConnectorStatus } from '../../lib/connectors/update_connector_status'; @@ -244,4 +245,28 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { return response.ok({ body: result }); }) ); + + router.put( + { + path: '/internal/enterprise_search/connectors/{connectorId}/name_and_description', + validate: { + params: schema.object({ + connectorId: schema.string(), + }), + body: schema.object({ + name: schema.maybe(schema.string()), + description: schema.maybe(schema.string()), + }), + }, + }, + elasticsearchErrorHandler(log, async (context, request, response) => { + const { client } = (await context.core).elasticsearch; + const { name, description } = request.body; + const result = await updateConnectorNameAndDescription(client, request.params.connectorId, { + description, + name, + }); + return response.ok({ body: result }); + }) + ); } diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts index b86f1dce83482..435fb0892019f 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts @@ -191,7 +191,7 @@ describe('Enterprise Search Managed Indices', () => { }); }); - describe('DELETE /internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/{pipelineName}', () => { + describe('DELETE /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/{pipelineName}', () => { const indexName = 'my-index'; const pipelineName = 'my-pipeline'; @@ -203,7 +203,7 @@ describe('Enterprise Search Managed Indices', () => { mockRouter = new MockRouter({ context, method: 'delete', - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/{pipelineName}', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/{pipelineName}', }); registerIndexRoutes({ @@ -267,7 +267,7 @@ describe('Enterprise Search Managed Indices', () => { }); }); - describe('POST /internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/_simulate', () => { + describe('POST /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/_simulate', () => { const pipelineBody = { description: 'Some pipeline', processors: [ @@ -299,7 +299,7 @@ describe('Enterprise Search Managed Indices', () => { mockRouter = new MockRouter({ context, method: 'post', - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/_simulate', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/_simulate', }); registerIndexRoutes({ @@ -376,7 +376,7 @@ describe('Enterprise Search Managed Indices', () => { }); }); - describe('PUT /internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/{pipelineName}', () => { + describe('PUT /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/{pipelineName}', () => { const pipelineName = 'some-pipeline'; const indexName = 'some-index'; const pipelineBody = { @@ -399,7 +399,7 @@ describe('Enterprise Search Managed Indices', () => { mockRouter = new MockRouter({ context, method: 'put', - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/{pipelineName}', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/{pipelineName}', }); registerIndexRoutes({ diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts index be33bc6fbe2e3..d781258599b0a 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts @@ -39,6 +39,7 @@ import { isIndexNotFoundException, isResourceNotFoundException, } from '../../utils/identify_exceptions'; +import { getPrefixedInferencePipelineProcessorName } from '../../utils/ml_inference_pipeline_utils'; export function registerIndexRoutes({ router, @@ -460,7 +461,7 @@ export function registerIndexRoutes({ router.post( { - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/_simulate', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/_simulate', validate: { body: schema.object({ pipeline: schema.object({ @@ -513,7 +514,7 @@ export function registerIndexRoutes({ router.put( { - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/{pipelineName}', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/{pipelineName}', validate: { body: schema.object({ description: schema.maybe(schema.string()), @@ -530,7 +531,7 @@ export function registerIndexRoutes({ const indexName = decodeURIComponent(request.params.indexName); const pipelineName = decodeURIComponent(request.params.pipelineName); const { client } = (await context.core).elasticsearch; - const pipelineId = `ml-inference-${pipelineName}`; + const pipelineId = getPrefixedInferencePipelineProcessorName(pipelineName); const defaultDescription = `ML inference pipeline for index ${indexName}`; if (!(await indexOrAliasExists(client, indexName))) { @@ -571,7 +572,7 @@ export function registerIndexRoutes({ router.delete( { - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipelines/{pipelineName}', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/{pipelineName}', validate: { params: schema.object({ indexName: schema.string(), diff --git a/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.test.ts b/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.test.ts index e4100a003eb81..c34bbae2f97f1 100644 --- a/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.test.ts +++ b/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.test.ts @@ -11,13 +11,17 @@ import { createMlInferencePipeline, addSubPipelineToIndexSpecificMlPipeline, } from './create_ml_inference_pipeline'; +import { + getInferencePipelineNameFromIndexName, + getPrefixedInferencePipelineProcessorName, +} from './ml_inference_pipeline_utils'; describe('createMlInferencePipeline util function', () => { const pipelineName = 'my-pipeline'; const modelId = 'my-model-id'; const sourceField = 'my-source-field'; const destinationField = 'my-dest-field'; - const inferencePipelineGeneratedName = `ml-inference-${pipelineName}`; + const inferencePipelineGeneratedName = getPrefixedInferencePipelineProcessorName(pipelineName); const mockClient = { ingest: { @@ -29,6 +33,18 @@ describe('createMlInferencePipeline util function', () => { }, }; + mockClient.ml.getTrainedModels.mockImplementation(() => + Promise.resolve({ + trained_model_configs: [ + { + input: { + field_names: ['target-field'], + }, + }, + ], + }) + ); + beforeEach(() => { jest.clearAllMocks(); }); @@ -36,17 +52,6 @@ describe('createMlInferencePipeline util function', () => { it("should create the pipeline if it doesn't exist", async () => { mockClient.ingest.getPipeline.mockImplementation(() => Promise.reject({ statusCode: 404 })); // Pipeline does not exist mockClient.ingest.putPipeline.mockImplementation(() => Promise.resolve({ acknowledged: true })); - mockClient.ml.getTrainedModels.mockImplementation(() => - Promise.resolve({ - trained_model_configs: [ - { - input: { - field_names: ['target-field'], - }, - }, - ], - }) - ); const expectedResult = { created: true, @@ -65,6 +70,22 @@ describe('createMlInferencePipeline util function', () => { expect(mockClient.ingest.putPipeline).toHaveBeenCalled(); }); + it('should convert spaces to underscores in the pipeline name', async () => { + await createMlInferencePipeline( + 'my pipeline with spaces ', + modelId, + sourceField, + destinationField, + mockClient as unknown as ElasticsearchClient + ); + + expect(mockClient.ingest.putPipeline).toHaveBeenCalledWith( + expect.objectContaining({ + id: 'ml-inference-my_pipeline_with_spaces', + }) + ); + }); + it('should throw an error without creating the pipeline if it already exists', () => { mockClient.ingest.getPipeline.mockImplementation(() => Promise.resolve({ @@ -87,7 +108,7 @@ describe('createMlInferencePipeline util function', () => { describe('addSubPipelineToIndexSpecificMlPipeline util function', () => { const indexName = 'my-index'; - const parentPipelineId = `${indexName}@ml-inference`; + const parentPipelineId = getInferencePipelineNameFromIndexName(indexName); const pipelineName = 'ml-inference-my-pipeline'; const mockClient = { diff --git a/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.ts b/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.ts index 3e1b51efabaf8..7131b4bc5cf81 100644 --- a/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.ts +++ b/x-pack/plugins/enterprise_search/server/utils/create_ml_inference_pipeline.ts @@ -12,6 +12,11 @@ import { ErrorCode } from '../../common/types/error_codes'; import { formatMlPipelineBody } from '../lib/pipelines/create_pipeline_definitions'; +import { + getInferencePipelineNameFromIndexName, + getPrefixedInferencePipelineProcessorName, +} from './ml_inference_pipeline_utils'; + /** * Details of a created pipeline. */ @@ -74,7 +79,7 @@ export const createMlInferencePipeline = async ( destinationField: string, esClient: ElasticsearchClient ): Promise => { - const inferencePipelineGeneratedName = `ml-inference-${pipelineName}`; + const inferencePipelineGeneratedName = getPrefixedInferencePipelineProcessorName(pipelineName); // Check that a pipeline with the same name doesn't already exist let pipelineByName: IngestGetPipelineResponse | undefined; @@ -120,7 +125,7 @@ export const addSubPipelineToIndexSpecificMlPipeline = async ( pipelineName: string, esClient: ElasticsearchClient ): Promise => { - const parentPipelineId = `${indexName}@ml-inference`; + const parentPipelineId = getInferencePipelineNameFromIndexName(indexName); // Fetch the parent pipeline let parentPipeline: IngestPipeline | undefined; diff --git a/x-pack/plugins/enterprise_search/server/utils/ml_inference_pipeline_utils.ts b/x-pack/plugins/enterprise_search/server/utils/ml_inference_pipeline_utils.ts new file mode 100644 index 0000000000000..e059f5b9090c0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/ml_inference_pipeline_utils.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const getInferencePipelineNameFromIndexName = (indexName: string) => + `${indexName}@ml-inference`; + +export const getPrefixedInferencePipelineProcessorName = (pipelineName: string) => + pipelineName.startsWith('ml-inference-') + ? formatPipelineName(pipelineName) + : `ml-inference-${formatPipelineName(pipelineName)}`; + +const formatPipelineName = (rawName: string) => + rawName + .trim() + .replace(/\s+/g, '_') // Convert whitespaces to underscores + .toLowerCase(); diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 60c4dd7fd8975..138279d7b7f5a 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -557,6 +557,18 @@ ] }, "savedObject": { + "type": "object" + }, + "latestVersion": { + "type": "string" + }, + "keepPoliciesUpToDate": { + "type": "boolean" + }, + "notice": { + "type": "string" + }, + "licensePath": { "type": "string" } }, @@ -4194,6 +4206,26 @@ "version": { "type": "string" }, + "release": { + "type": "string", + "enum": [ + "experimental", + "beta", + "ga" + ] + }, + "source": { + "type": "object", + "properties": { + "license": { + "type": "string", + "enum": [ + "Apache-2.0", + "Elastic-2.0" + ] + } + } + }, "readme": { "type": "string" }, @@ -4209,34 +4241,32 @@ "type": "string" } }, - "requirement": { - "oneOf": [ - { + "conditions": { + "type": "object", + "properties": { + "kibana": { + "type": "object", "properties": { - "kibana": { - "type": "object", - "properties": { - "versions": { - "type": "string" - } - } + "versions": { + "type": "string" } } }, - { + "elasticsearch": { + "type": "object", "properties": { - "elasticsearch": { - "type": "object", - "properties": { - "versions": { - "type": "string" - } - } + "subscription": { + "type": "string", + "enum": [ + "basic", + "gold", + "platinum", + "enterprise" + ] } } } - ], - "type": "object" + } }, "screenshots": { "type": "array", @@ -4340,6 +4370,22 @@ }, "path": { "type": "string" + }, + "elasticsearch": { + "type": "object", + "properties": { + "privileges": { + "type": "object", + "properties": { + "cluster": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } } }, "required": [ @@ -4349,7 +4395,7 @@ "description", "type", "categories", - "requirement", + "conditions", "assets", "format_version", "download", diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 567ee06825b92..60c305097c4cc 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -350,6 +350,14 @@ paths: - install_failed - not_installed savedObject: + type: object + latestVersion: + type: string + keepPoliciesUpToDate: + type: boolean + notice: + type: string + licensePath: type: string required: - status @@ -2623,6 +2631,20 @@ components: type: string version: type: string + release: + type: string + enum: + - experimental + - beta + - ga + source: + type: object + properties: + license: + type: string + enum: + - Apache-2.0 + - Elastic-2.0 readme: type: string description: @@ -2633,21 +2655,24 @@ components: type: array items: type: string - requirement: - oneOf: - - properties: - kibana: - type: object - properties: - versions: - type: string - - properties: - elasticsearch: - type: object - properties: - versions: - type: string + conditions: type: object + properties: + kibana: + type: object + properties: + versions: + type: string + elasticsearch: + type: object + properties: + subscription: + type: string + enum: + - basic + - gold + - platinum + - enterprise screenshots: type: array items: @@ -2718,6 +2743,16 @@ components: type: string path: type: string + elasticsearch: + type: object + properties: + privileges: + type: object + properties: + cluster: + type: array + items: + type: string required: - name - title @@ -2725,7 +2760,7 @@ components: - description - type - categories - - requirement + - conditions - assets - format_version - download diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/package_info.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/package_info.yaml index e61c349f3f490..80c777a07718c 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/package_info.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/package_info.yaml @@ -7,6 +7,20 @@ properties: type: string version: type: string + release: + type: string + enum: + - experimental + - beta + - ga + source: + type: object + properties: + license: + type: string + enum: + - Apache-2.0 + - Elastic-2.0 readme: type: string description: @@ -17,21 +31,24 @@ properties: type: array items: type: string - requirement: - oneOf: - - properties: - kibana: - type: object - properties: - versions: - type: string - - properties: - elasticsearch: - type: object - properties: - versions: - type: string + conditions: type: object + properties: + kibana: + type: object + properties: + versions: + type: string + elasticsearch: + type: object + properties: + subscription: + type: string + enum: + - basic + - gold + - platinum + - enterprise screenshots: type: array items: @@ -102,6 +119,16 @@ properties: type: string path: type: string + elasticsearch: + type: object + properties: + privileges: + type: object + properties: + cluster: + type: array + items: + type: string required: - name - title @@ -109,7 +136,7 @@ required: - description - type - categories - - requirement + - conditions - assets - format_version - download diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml index 6ef61788acd62..8164d04fc98f1 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml @@ -21,6 +21,14 @@ get: - install_failed - not_installed savedObject: + type: object + latestVersion: + type: string + keepPoliciesUpToDate: + type: boolean + notice: + type: string + licensePath: type: string required: - status diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index b2742b0d36886..b25266db5407c 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -57,7 +57,7 @@ export type DetailViewPanelName = | 'api-reference'; export type ServiceName = 'kibana' | 'elasticsearch'; export type AgentAssetType = typeof agentAssetTypes; -export type DocAssetType = 'doc' | 'notice'; +export type DocAssetType = 'doc' | 'notice' | 'license'; export type AssetType = | KibanaAssetType | ElasticsearchAssetType @@ -404,6 +404,7 @@ export interface EpmPackageAdditions { latestVersion: string; assets: AssetsGroupedByServiceByType; notice?: string; + licensePath?: string; keepPoliciesUpToDate?: boolean; } diff --git a/x-pack/plugins/fleet/common/types/models/package_spec.ts b/x-pack/plugins/fleet/common/types/models/package_spec.ts index 4d79b5167bf58..4463bb81097e2 100644 --- a/x-pack/plugins/fleet/common/types/models/package_spec.ts +++ b/x-pack/plugins/fleet/common/types/models/package_spec.ts @@ -15,6 +15,9 @@ export interface PackageSpecManifest { description: string; version: string; license?: 'basic'; + source?: { + license: string; + }; type?: 'integration' | 'input'; release?: 'experimental' | 'beta' | 'ga'; categories?: Array; @@ -54,12 +57,14 @@ export type PackageSpecCategory = | 'version_control' | 'web'; -export type PackageSpecConditions = Record< - 'kibana', - { +export interface PackageSpecConditions { + kibana: { version: string; - } ->; + }; + elastic?: { + subscription: string; + }; +} export interface PackageSpecIcon { src: string; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.test.tsx index 86748a8644c79..daf8177b9e73e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.test.tsx @@ -102,4 +102,50 @@ describe('useHistoryBlock', () => { expect(renderer.startServices.application.navigateToUrl).not.toBeCalled(); }); }); + + describe('with hash params', () => { + it('should not block if not edited', () => { + const renderer = createFleetTestRendererMock(); + + renderer.renderHook(() => useHistoryBlock(false)); + + act(() => renderer.mountHistory.push('/test#/hash')); + + const { location } = renderer.mountHistory; + expect(location.pathname).toBe('/test'); + expect(location.hash).toBe('#/hash'); + expect(renderer.startServices.overlays.openConfirm).not.toBeCalled(); + }); + + it('should block if edited and navigate on confirm', async () => { + const renderer = createFleetTestRendererMock(); + + renderer.startServices.overlays.openConfirm.mockResolvedValue(true); + renderer.renderHook(() => useHistoryBlock(true)); + + act(() => renderer.mountHistory.push('/test#/hash')); + // needed because we have an async useEffect + await act(() => new Promise((resolve) => resolve())); + + expect(renderer.startServices.overlays.openConfirm).toBeCalled(); + expect(renderer.startServices.application.navigateToUrl).toBeCalledWith( + '/mock/test#/hash', + expect.anything() + ); + }); + + it('should block if edited and not navigate on cancel', async () => { + const renderer = createFleetTestRendererMock(); + + renderer.startServices.overlays.openConfirm.mockResolvedValue(false); + renderer.renderHook(() => useHistoryBlock(true)); + + act(() => renderer.mountHistory.push('/test#/hash')); + // needed because we have an async useEffect + await act(() => new Promise((resolve) => resolve())); + + expect(renderer.startServices.overlays.openConfirm).toBeCalled(); + expect(renderer.startServices.application.navigateToUrl).not.toBeCalled(); + }); + }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.tsx index 8e04fbddd2ccc..edf04f8733ad8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/index.tsx @@ -35,7 +35,10 @@ export function useHistoryBlock(isEdited: boolean) { if (confirmRes) { unblock(); - application.navigateToUrl(state.pathname + state.search, { state: state.state }); + + application.navigateToUrl(state.pathname + state.hash + state.search, { + state: state.state, + }); } } confirmAsync(); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx index 875d43d1f0ea4..51831fdfa6b7c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/services/devtools_request.tsx @@ -105,7 +105,7 @@ function formatVars(vars: NewPackagePolicy['inputs'][number]['vars']) { } return Object.entries(vars).reduce((acc, [varKey, varRecord]) => { - acc[varKey] = varRecord.value; + acc[varKey] = varRecord?.value; return acc; }, {} as SimplifiedVars); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx index c65749178ddee..8d130c04bac5d 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets.tsx @@ -8,7 +8,7 @@ import React, { useEffect, useState } from 'react'; import { Redirect } from 'react-router-dom'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { groupBy } from 'lodash'; import type { ResolvedSimpleSavedObject } from '@kbn/core/public'; @@ -52,6 +52,7 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => { const [assetSavedObjects, setAssetsSavedObjects] = useState(); const [fetchError, setFetchError] = useState(); const [isLoading, setIsLoading] = useState(true); + const [hasPermissionError, setHasPermissionError] = useState(false); useEffect(() => { const fetchAssetSavedObjects = async () => { @@ -94,6 +95,7 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => { // Ignore privilege errors .catch((e: any) => { if (e?.body?.statusCode === 403) { + setHasPermissionError(true); return { resolved_objects: [] }; } else { throw e; @@ -161,6 +163,23 @@ export const AssetsPage = ({ packageInfo }: AssetsPanelProps) => { ); + } else if (hasPermissionError) { + content = ( + + } + > + + + ); } else if (assetSavedObjects === undefined || assetSavedObjects.length === 0) { if (customAssetsExtension) { // If a UI extension for custom asset entries is defined, render the custom component here despite diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx index 162c9cb0d9efe..729975e8e8e37 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx @@ -33,6 +33,7 @@ import { useGetCategories } from '../../../../../hooks'; import { AssetTitleMap, DisplayedAssets, ServiceTitleMap } from '../../../constants'; import { NoticeModal } from './notice_modal'; +import { LicenseModal } from './license_modal'; const ReplacementCard = withSuspense(LazyReplacementCard); @@ -73,6 +74,11 @@ export const Details: React.FC = memo(({ packageInfo }) => { setIsNoticeModalOpen(!isNoticeModalOpen); }, [isNoticeModalOpen]); + const [isLicenseModalOpen, setIsLicenseModalOpen] = useState(false); + const toggleLicenseModal = useCallback(() => { + setIsLicenseModalOpen(!isLicenseModalOpen); + }, [isLicenseModalOpen]); + const listItems = useMemo(() => { // Base details: version and categories const items: EuiDescriptionListProps['listItems'] = [ @@ -154,8 +160,20 @@ export const Details: React.FC = memo(({ packageInfo }) => { }); } + // Subscription details + items.push({ + title: ( + + + + ), + description: ( +

{packageInfo.conditions?.elastic?.subscription || packageInfo.license || '-'}

+ ), + }); + // License details - if (packageInfo.license || packageInfo.notice) { + if (packageInfo.licensePath || packageInfo.source?.license || packageInfo.notice) { items.push({ title: ( @@ -164,7 +182,15 @@ export const Details: React.FC = memo(({ packageInfo }) => { ), description: ( <> -

{packageInfo.license}

+ {packageInfo.licensePath ? ( +

+ + {packageInfo.source?.license || 'LICENSE.txt'} + +

+ ) : ( +

{packageInfo.source?.license || '-'}

+ )} {packageInfo.notice && (

NOTICE.txt @@ -179,10 +205,14 @@ export const Details: React.FC = memo(({ packageInfo }) => { }, [ packageCategories, packageInfo.assets, + packageInfo.conditions?.elastic?.subscription, packageInfo.data_streams, packageInfo.license, + packageInfo.licensePath, packageInfo.notice, + packageInfo.source?.license, packageInfo.version, + toggleLicenseModal, toggleNoticeModal, ]); @@ -193,6 +223,15 @@ export const Details: React.FC = memo(({ packageInfo }) => { )} + + {isLicenseModalOpen && packageInfo.licensePath && ( + + )} + diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/license_modal.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/license_modal.tsx new file mode 100644 index 0000000000000..eafdbfb2debe2 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/license_modal.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState } from 'react'; +import { + EuiCodeBlock, + EuiLoadingContent, + EuiModal, + EuiModalBody, + EuiModalHeader, + EuiModalFooter, + EuiModalHeaderTitle, + EuiButton, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import { sendGetFileByPath, useStartServices } from '../../../../../hooks'; + +interface Props { + licenseName?: string; + licensePath: string; + onClose: () => void; +} + +export const LicenseModal: React.FunctionComponent = ({ + licenseName = 'LICENSE.txt', + licensePath, + onClose, +}) => { + const { notifications } = useStartServices(); + const [licenseText, setLicenseText] = useState(undefined); + + useEffect(() => { + async function fetchData() { + try { + const { data } = await sendGetFileByPath(licensePath); + setLicenseText(data || ''); + } catch (err) { + notifications.toasts.addError(err, { + title: i18n.translate('xpack.fleet.epm.errorLoadingLicense', { + defaultMessage: 'Error loading license information', + }), + }); + } + } + fetchData(); + }, [licensePath, notifications]); + return ( + + + +

{licenseName}

+ + + + + {licenseText ? ( + licenseText + ) : ( + // Simulate a long text while loading + <> +

+ +

+

+ +

+ + )} +
+
+ + + + + + + ); +}; diff --git a/x-pack/plugins/fleet/server/mocks/index.ts b/x-pack/plugins/fleet/server/mocks/index.ts index 47a918ed377f0..eb98d0e68eca8 100644 --- a/x-pack/plugins/fleet/server/mocks/index.ts +++ b/x-pack/plugins/fleet/server/mocks/index.ts @@ -120,6 +120,7 @@ export const createPackagePolicyServiceMock = (): jest.Mocked // There are some potential performance concerns around using `agentPolicyService.update` in this context. // This could potentially be a bottleneck in environments with several thousand agent policies being deployed here. - agentPolicyService.update(soClient, esClient, fleetServerPolicy.policy_id, { - schema_version: FLEET_AGENT_POLICIES_SCHEMA_VERSION, - }) + agentPolicyService.update( + soClient, + esClient, + fleetServerPolicy.policy_id, + { + schema_version: FLEET_AGENT_POLICIES_SCHEMA_VERSION, + }, + { force: true } + ) ) ); } diff --git a/x-pack/plugins/fleet/server/services/epm/archive/index.ts b/x-pack/plugins/fleet/server/services/epm/archive/index.ts index 4d70c62bd55d3..330839b13dba9 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/index.ts @@ -123,6 +123,13 @@ export function getPathParts(path: string): AssetParts { service = ''; } + // To support the LICENSE asset at the root level + if (service === 'LICENSE.txt') { + file = service; + type = 'license'; + service = ''; + } + // This is to cover for the fields.yml files inside the "fields" directory if (file === undefined) { file = type; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index dab8f3c0bf82e..527b93a66d130 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -223,7 +223,7 @@ type UserSettingsTemplateName = `${TemplateBaseName}${typeof USER_SETTINGS_TEMPL const isUserSettingsTemplate = (name: string): name is UserSettingsTemplateName => name.endsWith(USER_SETTINGS_TEMPLATE_SUFFIX); -function buildComponentTemplates(params: { +export function buildComponentTemplates(params: { mappings: IndexTemplateMappings; templateName: string; registryElasticsearch: RegistryElasticsearch | undefined; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts index ab8f60e172dcb..8c908ecc9ef87 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts @@ -7,65 +7,71 @@ import type { ElasticsearchClient, Logger, SavedObjectsClientContract } from '@kbn/core/server'; import { errors } from '@elastic/elasticsearch'; +import { safeLoad } from 'js-yaml'; +import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { + PACKAGE_TEMPLATE_SUFFIX, + USER_SETTINGS_TEMPLATE_SUFFIX, +} from '../../../../../common/constants'; +import { + buildComponentTemplates, + installComponentAndIndexTemplateForDataStream, +} from '../template/install'; +import { processFields } from '../../fields/field'; +import { generateMappings } from '../template/template'; +import { getESAssetMetadata } from '../meta'; import { updateEsAssetReferences } from '../../packages/install'; import { getPathParts } from '../../archive'; import { ElasticsearchAssetType } from '../../../../../common/types/models'; -import type { EsAssetReference, InstallablePackage } from '../../../../../common/types/models'; +import type { + EsAssetReference, + InstallablePackage, + ESAssetMetadata, + IndexTemplate, + RegistryElasticsearch, +} from '../../../../../common/types/models'; import { getInstallation } from '../../packages'; - -import { getESAssetMetadata } from '../meta'; - import { retryTransientEsErrors } from '../retry'; import { deleteTransforms } from './remove'; import { getAsset } from './common'; -interface TransformInstallation { +const DEFAULT_TRANSFORM_TEMPLATES_PRIORITY = 250; +enum TRANSFORM_SPECS_TYPES { + MANIFEST = 'manifest', + FIELDS = 'fields', + TRANSFORM = 'transform', +} + +interface TransformModuleBase { + transformModuleId?: string; +} +interface DestinationIndexTemplateInstallation extends TransformModuleBase { + installationName: string; + _meta: ESAssetMetadata; + template: IndexTemplate['template']; +} +interface TransformInstallation extends TransformModuleBase { installationName: string; content: any; } -export const installTransform = async ( +const installLegacyTransformsAssets = async ( installablePackage: InstallablePackage, - paths: string[], + installNameSuffix: string, + transformPaths: string[], esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClientContract, logger: Logger, - esReferences?: EsAssetReference[] + esReferences: EsAssetReference[] = [], + previousInstalledTransformEsAssets: EsAssetReference[] = [] ) => { - const installation = await getInstallation({ - savedObjectsClient, - pkgName: installablePackage.name, - }); - esReferences = esReferences ?? installation?.installed_es ?? []; - let previousInstalledTransformEsAssets: EsAssetReference[] = []; - if (installation) { - previousInstalledTransformEsAssets = installation.installed_es.filter( - ({ type, id }) => type === ElasticsearchAssetType.transform - ); - if (previousInstalledTransformEsAssets.length) { - logger.info( - `Found previous transform references:\n ${JSON.stringify( - previousInstalledTransformEsAssets - )}` - ); - } - } - - // delete all previous transform - await deleteTransforms( - esClient, - previousInstalledTransformEsAssets.map((asset) => asset.id) - ); - - const installNameSuffix = `${installablePackage.version}`; - const transformPaths = paths.filter((path) => isTransform(path)); let installedTransforms: EsAssetReference[] = []; if (transformPaths.length > 0) { const transformRefs = transformPaths.reduce((acc, path) => { acc.push({ - id: getTransformNameForInstallation(installablePackage, path, installNameSuffix), + id: getLegacyTransformNameForInstallation(installablePackage, path, installNameSuffix), type: ElasticsearchAssetType.transform, }); @@ -87,7 +93,7 @@ export const installTransform = async ( content._meta = getESAssetMetadata({ packageName: installablePackage.name }); return { - installationName: getTransformNameForInstallation( + installationName: getLegacyTransformNameForInstallation( installablePackage, path, installNameSuffix @@ -117,6 +123,289 @@ export const installTransform = async ( return { installedTransforms, esReferences }; }; +const processTransformAssetsPerModule = ( + installablePackage: InstallablePackage, + installNameSuffix: string, + transformPaths: string[] +) => { + const transformsSpecifications = new Map(); + const destinationIndexTemplates: DestinationIndexTemplateInstallation[] = []; + const transforms: TransformInstallation[] = []; + + transformPaths.forEach((path: string) => { + const { transformModuleId, fileName } = getTransformFolderAndFileNames( + installablePackage, + path + ); + + // Since there can be multiple assets per transform definition + // We want to create a unique list of assets/specifications for each transform + if (transformsSpecifications.get(transformModuleId) === undefined) { + transformsSpecifications.set(transformModuleId, new Map()); + } + const packageAssets = transformsSpecifications.get(transformModuleId); + + const content = safeLoad(getAsset(path).toString('utf-8')); + + if (fileName === TRANSFORM_SPECS_TYPES.FIELDS) { + const validFields = processFields(content); + const mappings = generateMappings(validFields); + packageAssets?.set('mappings', mappings); + } + + if (fileName === TRANSFORM_SPECS_TYPES.TRANSFORM) { + transformsSpecifications.get(transformModuleId)?.set('destinationIndex', content.dest); + transformsSpecifications.get(transformModuleId)?.set('transform', content); + content._meta = getESAssetMetadata({ packageName: installablePackage.name }); + transforms.push({ + transformModuleId, + installationName: getTransformAssetNameForInstallation( + installablePackage, + transformModuleId, + `default-${installNameSuffix}` + ), + content, + }); + } + + if (fileName === TRANSFORM_SPECS_TYPES.MANIFEST) { + if (isPopulatedObject(content, ['start']) && content.start === false) { + transformsSpecifications.get(transformModuleId)?.set('start', false); + } + // If manifest.yml contains destination_index_template + // Combine the mappings and other index template settings from manifest.yml into a single index template + // Create the index template and track the template in EsAssetReferences + if ( + isPopulatedObject(content, ['destination_index_template']) || + isPopulatedObject(packageAssets.get('mappings')) + ) { + const destinationIndexTemplate = + (content.destination_index_template as Record) ?? {}; + destinationIndexTemplates.push({ + transformModuleId, + _meta: getESAssetMetadata({ packageName: installablePackage.name }), + installationName: getTransformAssetNameForInstallation( + installablePackage, + transformModuleId, + 'template' + ), + template: destinationIndexTemplate, + } as DestinationIndexTemplateInstallation); + packageAssets.set('destinationIndexTemplate', destinationIndexTemplate); + } + } + }); + + const indexTemplatesRefs = destinationIndexTemplates.map((template) => ({ + id: template.installationName, + type: ElasticsearchAssetType.indexTemplate, + })); + const componentTemplatesRefs = [ + ...destinationIndexTemplates.map((template) => ({ + id: `${template.installationName}${USER_SETTINGS_TEMPLATE_SUFFIX}`, + type: ElasticsearchAssetType.componentTemplate, + })), + ...destinationIndexTemplates.map((template) => ({ + id: `${template.installationName}${PACKAGE_TEMPLATE_SUFFIX}`, + type: ElasticsearchAssetType.componentTemplate, + })), + ]; + + const transformRefs = transforms.map((t) => ({ + id: t.installationName, + type: ElasticsearchAssetType.transform, + })); + + return { + indexTemplatesRefs, + componentTemplatesRefs, + transformRefs, + transforms, + destinationIndexTemplates, + transformsSpecifications, + }; +}; + +const installTransformsAssets = async ( + installablePackage: InstallablePackage, + installNameSuffix: string, + transformPaths: string[], + esClient: ElasticsearchClient, + savedObjectsClient: SavedObjectsClientContract, + logger: Logger, + esReferences: EsAssetReference[] = [], + previousInstalledTransformEsAssets: EsAssetReference[] = [] +) => { + let installedTransforms: EsAssetReference[] = []; + if (transformPaths.length > 0) { + const { + indexTemplatesRefs, + componentTemplatesRefs, + transformRefs, + transforms, + destinationIndexTemplates, + transformsSpecifications, + } = processTransformAssetsPerModule(installablePackage, installNameSuffix, transformPaths); + // get and save refs associated with the transforms before installing + esReferences = await updateEsAssetReferences( + savedObjectsClient, + installablePackage.name, + esReferences, + { + assetsToAdd: [...indexTemplatesRefs, ...componentTemplatesRefs, ...transformRefs], + assetsToRemove: previousInstalledTransformEsAssets, + } + ); + + // create index templates and component templates + await Promise.all( + destinationIndexTemplates + .map((destinationIndexTemplate) => { + const customMappings = transformsSpecifications + .get(destinationIndexTemplate.transformModuleId) + ?.get('mappings'); + const registryElasticsearch: RegistryElasticsearch = { + 'index_template.settings': destinationIndexTemplate.template.settings, + 'index_template.mappings': destinationIndexTemplate.template.mappings, + }; + + const componentTemplates = buildComponentTemplates({ + mappings: customMappings, + templateName: destinationIndexTemplate.installationName, + registryElasticsearch, + packageName: installablePackage.name, + defaultSettings: {}, + }); + + if (destinationIndexTemplate || customMappings) { + return installComponentAndIndexTemplateForDataStream({ + esClient, + logger, + componentTemplates, + indexTemplate: { + templateName: destinationIndexTemplate.installationName, + // @ts-expect-error We don't need to pass data_stream property here + // as this template is applied to only an index and not a data stream + indexTemplate: { + template: { settings: undefined, mappings: undefined }, + priority: DEFAULT_TRANSFORM_TEMPLATES_PRIORITY, + index_patterns: [ + transformsSpecifications + .get(destinationIndexTemplate.transformModuleId) + ?.get('destinationIndex').index, + ], + _meta: destinationIndexTemplate._meta, + composed_of: Object.keys(componentTemplates), + }, + }, + }); + } + }) + .filter((p) => p !== undefined) + ); + + // create destination indices + await Promise.all( + transforms.map(async (transform) => { + const index = transform.content.dest.index; + const pipelineId = transform.content.dest.pipeline; + + try { + await retryTransientEsErrors( + () => + esClient.indices.create( + { + index, + ...(pipelineId ? { settings: { default_pipeline: pipelineId } } : {}), + }, + { ignore: [400] } + ), + { logger } + ); + } catch (err) { + throw new Error(err.message); + } + }) + ); + + // create & optionally start transforms + const transformsPromises = transforms.map(async (transform) => { + return handleTransformInstall({ + esClient, + logger, + transform, + startTransform: transformsSpecifications.get(transform.transformModuleId)?.get('start'), + }); + }); + + installedTransforms = await Promise.all(transformsPromises).then((results) => results.flat()); + } + + return { installedTransforms, esReferences }; +}; +export const installTransforms = async ( + installablePackage: InstallablePackage, + paths: string[], + esClient: ElasticsearchClient, + savedObjectsClient: SavedObjectsClientContract, + logger: Logger, + esReferences?: EsAssetReference[] +) => { + const transformPaths = paths.filter((path) => isTransform(path)); + + const installation = await getInstallation({ + savedObjectsClient, + pkgName: installablePackage.name, + }); + esReferences = esReferences ?? installation?.installed_es ?? []; + let previousInstalledTransformEsAssets: EsAssetReference[] = []; + if (installation) { + previousInstalledTransformEsAssets = installation.installed_es.filter( + ({ type, id }) => type === ElasticsearchAssetType.transform + ); + if (previousInstalledTransformEsAssets.length) { + logger.debug( + `Found previous transform references:\n ${JSON.stringify( + previousInstalledTransformEsAssets + )}` + ); + } + } + + // delete all previous transform + await deleteTransforms( + esClient, + previousInstalledTransformEsAssets.map((asset) => asset.id) + ); + + const installNameSuffix = `${installablePackage.version}`; + + // If package contains legacy transform specifications (i.e. with json instead of yml) + if (transformPaths.some((p) => p.endsWith('.json')) || transformPaths.length === 0) { + return await installLegacyTransformsAssets( + installablePackage, + installNameSuffix, + transformPaths, + esClient, + savedObjectsClient, + logger, + esReferences, + previousInstalledTransformEsAssets + ); + } + + return await installTransformsAssets( + installablePackage, + installNameSuffix, + transformPaths, + esClient, + savedObjectsClient, + logger, + esReferences, + previousInstalledTransformEsAssets + ); +}; + export const isTransform = (path: string) => { const pathParts = getPathParts(path); return !path.endsWith('/') && pathParts.type === ElasticsearchAssetType.transform; @@ -126,10 +415,12 @@ async function handleTransformInstall({ esClient, logger, transform, + startTransform, }: { esClient: ElasticsearchClient; logger: Logger; transform: TransformInstallation; + startTransform?: boolean; }): Promise { try { await retryTransientEsErrors( @@ -151,15 +442,21 @@ async function handleTransformInstall({ throw err; } } - await esClient.transform.startTransform( - { transform_id: transform.installationName }, - { ignore: [409] } - ); + + // start transform by default if not set in yml file + // else, respect the setting + if (startTransform === undefined || startTransform === true) { + await esClient.transform.startTransform( + { transform_id: transform.installationName }, + { ignore: [409] } + ); + logger.debug(`Started transform: ${transform.installationName}`); + } return { id: transform.installationName, type: ElasticsearchAssetType.transform }; } -const getTransformNameForInstallation = ( +const getLegacyTransformNameForInstallation = ( installablePackage: InstallablePackage, path: string, suffix: string @@ -169,3 +466,24 @@ const getTransformNameForInstallation = ( const folderName = pathPaths?.pop(); return `${installablePackage.name}.${folderName}-${filename}-${suffix}`; }; + +const getTransformAssetNameForInstallation = ( + installablePackage: InstallablePackage, + transformModuleId: string, + suffix?: string +) => { + return `logs-${installablePackage.name}.${transformModuleId}${suffix ? '-' + suffix : ''}`; +}; + +const getTransformFolderAndFileNames = (installablePackage: InstallablePackage, path: string) => { + const pathPaths = path.split('/'); + const fileName = pathPaths?.pop()?.split('.')[0]; + let transformModuleId = pathPaths?.pop(); + + // If fields.yml is located inside a directory called 'fields' (e.g. {exampleFolder}/fields/fields.yml) + // We need to go one level up to get the real folder name + if (transformModuleId === 'fields') { + transformModuleId = pathPaths?.pop(); + } + return { fileName: fileName ?? '', transformModuleId: transformModuleId ?? '' }; +}; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts index 1b8c347ad07d5..97fa1e94ca218 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts @@ -35,7 +35,7 @@ import { getESAssetMetadata } from '../meta'; import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../constants'; import { getAsset } from './common'; -import { installTransform } from './install'; +import { installTransforms } from './install'; describe('test transform install', () => { let esClient: ReturnType; @@ -122,7 +122,7 @@ describe('test transform install', () => { ], }); - await installTransform( + await installTransforms( { name: 'endpoint', version: '0.16.0-dev.0', @@ -320,7 +320,7 @@ describe('test transform install', () => { } as unknown as SavedObject) ); - await installTransform( + await installTransforms( { name: 'endpoint', version: '0.16.0-dev.0', @@ -422,7 +422,7 @@ describe('test transform install', () => { ], }); - await installTransform( + await installTransforms( { name: 'endpoint', version: '0.16.0-dev.0', @@ -556,7 +556,7 @@ describe('test transform install', () => { ) ); - await installTransform( + await installTransforms( { name: 'endpoint', version: '0.16.0-dev.0', diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.test.ts b/x-pack/plugins/fleet/server/services/epm/package_service.test.ts index 1dc4039a7c2a7..4f98776f53d60 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.test.ts @@ -128,7 +128,7 @@ function getTest( test = { method: mocks.packageClient.reinstallEsAssets.bind(mocks.packageClient), args: [pkg, paths], - spy: jest.spyOn(epmTransformsInstall, 'installTransform'), + spy: jest.spyOn(epmTransformsInstall, 'installTransforms'), spyArgs: [pkg, paths, mocks.esClient, mocks.soClient, mocks.logger], spyResponse: { installedTransforms: [ diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.ts b/x-pack/plugins/fleet/server/services/epm/package_service.ts index c43386acdbdf4..71ab87c7d92bd 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.ts @@ -24,7 +24,7 @@ import type { import { checkSuperuser } from '../../routes/security'; import { FleetUnauthorizedError } from '../../errors'; -import { installTransform, isTransform } from './elasticsearch/transform/install'; +import { installTransforms, isTransform } from './elasticsearch/transform/install'; import { fetchFindLatestPackageOrThrow, getRegistryPackage } from './registry'; import { ensureInstalledPackage, getInstallation } from './packages'; @@ -151,7 +151,7 @@ class PackageClientImpl implements PackageClient { } async #reinstallTransforms(packageInfo: InstallablePackage, paths: string[]) { - const { installedTransforms } = await installTransform( + const { installedTransforms } = await installTransforms( packageInfo, paths, this.internalEsClient, diff --git a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts index 8168bb05e53a4..4ecec17560731 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/_install_package.ts @@ -42,7 +42,7 @@ import { import { installILMPolicy } from '../elasticsearch/ilm/install'; import { installKibanaAssetsAndReferences } from '../kibana/assets/install'; import { updateCurrentWriteIndices } from '../elasticsearch/template/template'; -import { installTransform } from '../elasticsearch/transform/install'; +import { installTransforms } from '../elasticsearch/transform/install'; import { installMlModel } from '../elasticsearch/ml_model'; import { installIlmForDataStream } from '../elasticsearch/datastream_ilm/install'; import { saveArchiveEntries } from '../archive/storage'; @@ -219,7 +219,7 @@ export async function _installPackage({ ); ({ esReferences } = await withPackageSpan('Install transforms', () => - installTransform(packageInfo, paths, esClient, savedObjectsClient, logger, esReferences) + installTransforms(packageInfo, paths, esClient, savedObjectsClient, logger, esReferences) )); // If this is an update or retrying an update, delete the previous version's pipelines diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index e69c5fe3944f0..c333ba9f7bc3d 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -181,6 +181,7 @@ export async function getPackageInfo({ title: packageInfo.title || nameAsTitle(packageInfo.name), assets: Registry.groupPathsByService(paths || []), notice: Registry.getNoticePath(paths || []), + licensePath: Registry.getLicensePath(paths || []), keepPoliciesUpToDate: savedObject?.attributes.keep_policies_up_to_date ?? false, }; const updated = { ...packageInfo, ...additions }; diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts index e9427732d4aef..ba309a15b04ee 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.test.ts @@ -9,7 +9,12 @@ import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { PackageNotFoundError } from '../../../errors'; -import { splitPkgKey, fetchFindLatestPackageOrUndefined, fetchFindLatestPackageOrThrow } from '.'; +import { + splitPkgKey, + fetchFindLatestPackageOrUndefined, + fetchFindLatestPackageOrThrow, + getLicensePath, +} from '.'; const mockLoggerFactory = loggingSystemMock.create(); const mockLogger = mockLoggerFactory.get('mock logger'); @@ -143,3 +148,26 @@ describe('fetch package', () => { }); }); }); + +describe('getLicensePath', () => { + it('returns first license path if found', () => { + const path = getLicensePath([ + '/package/good-1.0.0/NOTICE.txt', + '/package/good-1.0.0/changelog.yml', + '/package/good-1.0.0/manifest.yml', + '/package/good-1.0.0/LICENSE.txt', + '/package/good-1.0.0/docs/README.md', + ]); + expect(path).toEqual('/package/good/1.0.0/LICENSE.txt'); + }); + + it('returns undefined if no license', () => { + const path = getLicensePath([ + '/package/good-1.0.0/NOTICE.txt', + '/package/good-1.0.0/changelog.yml', + '/package/good-1.0.0/manifest.yml', + '/package/good-1.0.0/docs/README.md', + ]); + expect(path).toEqual(undefined); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.ts index 0302c0188cc2c..fee603f188e29 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.ts @@ -392,3 +392,15 @@ export function getNoticePath(paths: string[]): string | undefined { return undefined; } + +export function getLicensePath(paths: string[]): string | undefined { + for (const path of paths) { + const parts = getPathParts(path.replace(/^\/package\//, '')); + if (parts.type === 'license') { + const { pkgName, pkgVersion } = splitPkgKey(parts.pkgkey); + return `/package/${pkgName}/${pkgVersion}/${parts.file}`; + } + } + + return undefined; +} diff --git a/x-pack/plugins/fleet/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts index b2b0fd20104cc..9bbeb8fd67232 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.test.ts @@ -1142,6 +1142,540 @@ describe('Package policy service', () => { }); }); + describe('bulkUpdate', () => { + beforeEach(() => { + appContextService.start(createAppContextStartContractMock()); + }); + afterEach(() => { + appContextService.stop(); + }); + + it('should throw if the user try to update input vars that are frozen', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const mockPackagePolicy = createPackagePolicyMock(); + const mockInputs = [ + { + config: {}, + enabled: true, + keep_enabled: true, + type: 'endpoint', + vars: { + dog: { + type: 'text', + value: 'dalmatian', + }, + cat: { + type: 'text', + value: 'siamese', + frozen: true, + }, + }, + streams: [ + { + data_stream: { + type: 'birds', + dataset: 'migratory.patterns', + }, + enabled: false, + id: `endpoint-migratory.patterns-${mockPackagePolicy.id}`, + vars: { + paths: { + value: ['north', 'south'], + type: 'text', + frozen: true, + }, + period: { + value: '6mo', + type: 'text', + }, + }, + }, + ], + }, + ]; + const inputsUpdate = [ + { + config: {}, + enabled: false, + type: 'endpoint', + vars: { + dog: { + type: 'text', + value: 'labrador', + }, + cat: { + type: 'text', + value: 'tabby', + }, + }, + streams: [ + { + data_stream: { + type: 'birds', + dataset: 'migratory.patterns', + }, + enabled: false, + id: `endpoint-migratory.patterns-${mockPackagePolicy.id}`, + vars: { + paths: { + value: ['east', 'west'], + type: 'text', + }, + period: { + value: '12mo', + type: 'text', + }, + }, + }, + ], + }, + ]; + const attributes = { + ...mockPackagePolicy, + inputs: mockInputs, + }; + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes, + }, + ], + }); + + savedObjectsClient.update.mockImplementation( + async ( + type: string, + id: string, + attrs: any + ): Promise> => { + savedObjectsClient.get.mockResolvedValue({ + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes: attrs, + }); + return attrs; + } + ); + const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + const res = packagePolicyService.bulkUpdate( + savedObjectsClient, + elasticsearchClient, + + [{ ...mockPackagePolicy, inputs: inputsUpdate }] + ); + + await expect(res).rejects.toThrow('cat is a frozen variable and cannot be modified'); + }); + + it('should allow to update input vars that are frozen with the force flag', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const mockPackagePolicy = createPackagePolicyMock(); + const mockInputs = [ + { + config: {}, + enabled: true, + keep_enabled: true, + type: 'endpoint', + vars: { + dog: { + type: 'text', + value: 'dalmatian', + }, + cat: { + type: 'text', + value: 'siamese', + frozen: true, + }, + }, + streams: [ + { + data_stream: { + type: 'birds', + dataset: 'migratory.patterns', + }, + enabled: false, + id: `endpoint-migratory.patterns-${mockPackagePolicy.id}`, + vars: { + paths: { + value: ['north', 'south'], + type: 'text', + frozen: true, + }, + period: { + value: '6mo', + type: 'text', + }, + }, + }, + ], + }, + ]; + const inputsUpdate = [ + { + config: {}, + enabled: false, + type: 'endpoint', + vars: { + dog: { + type: 'text', + value: 'labrador', + }, + cat: { + type: 'text', + value: 'tabby', + }, + }, + streams: [ + { + data_stream: { + type: 'birds', + dataset: 'migratory.patterns', + }, + enabled: false, + id: `endpoint-migratory.patterns-${mockPackagePolicy.id}`, + vars: { + paths: { + value: ['east', 'west'], + type: 'text', + }, + period: { + value: '12mo', + type: 'text', + }, + }, + }, + ], + }, + ]; + const attributes = { + ...mockPackagePolicy, + inputs: mockInputs, + }; + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes, + }, + ], + }); + + savedObjectsClient.bulkUpdate.mockImplementation( + async ( + objs: Array<{ + type: string; + id: string; + attributes: any; + }> + ) => { + const newObjs = objs.map((obj) => ({ + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes: obj.attributes, + })); + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: newObjs, + }); + return { + saved_objects: newObjs, + }; + } + ); + const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + const result = await packagePolicyService.bulkUpdate( + savedObjectsClient, + elasticsearchClient, + [{ ...mockPackagePolicy, inputs: inputsUpdate }], + { force: true } + ); + + const [modifiedInput] = result![0].inputs; + expect(modifiedInput.enabled).toEqual(true); + expect(modifiedInput.vars!.dog.value).toEqual('labrador'); + expect(modifiedInput.vars!.cat.value).toEqual('tabby'); + const [modifiedStream] = modifiedInput.streams; + expect(modifiedStream.vars!.paths.value).toEqual(expect.arrayContaining(['east', 'west'])); + expect(modifiedStream.vars!.period.value).toEqual('12mo'); + }); + + it('should add new input vars when updating', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const mockPackagePolicy = createPackagePolicyMock(); + const mockInputs = [ + { + config: {}, + enabled: true, + keep_enabled: true, + type: 'endpoint', + vars: { + dog: { + type: 'text', + value: 'dalmatian', + }, + cat: { + type: 'text', + value: 'siamese', + frozen: true, + }, + }, + streams: [ + { + data_stream: { + type: 'birds', + dataset: 'migratory.patterns', + }, + enabled: false, + id: `endpoint-migratory.patterns-${mockPackagePolicy.id}`, + vars: { + paths: { + value: ['north', 'south'], + type: 'text', + frozen: true, + }, + }, + }, + ], + }, + ]; + const inputsUpdate = [ + { + config: {}, + enabled: false, + type: 'endpoint', + vars: { + dog: { + type: 'text', + value: 'labrador', + }, + cat: { + type: 'text', + value: 'siamese', + }, + }, + streams: [ + { + data_stream: { + type: 'birds', + dataset: 'migratory.patterns', + }, + enabled: false, + id: `endpoint-migratory.patterns-${mockPackagePolicy.id}`, + vars: { + paths: { + value: ['north', 'south'], + type: 'text', + }, + period: { + value: '12mo', + type: 'text', + }, + }, + }, + ], + }, + ]; + const attributes = { + ...mockPackagePolicy, + inputs: mockInputs, + }; + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes, + }, + ], + }); + + savedObjectsClient.bulkUpdate.mockImplementation( + async ( + objs: Array<{ + type: string; + id: string; + attributes: any; + }> + ) => { + const newObjs = objs.map((obj) => ({ + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes: obj.attributes, + })); + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: newObjs, + }); + return { + saved_objects: newObjs, + }; + } + ); + + const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + const result = await packagePolicyService.bulkUpdate( + savedObjectsClient, + elasticsearchClient, + [{ ...mockPackagePolicy, inputs: inputsUpdate }] + ); + + const [modifiedInput] = result![0].inputs; + expect(modifiedInput.enabled).toEqual(true); + expect(modifiedInput.vars!.dog.value).toEqual('labrador'); + expect(modifiedInput.vars!.cat.value).toEqual('siamese'); + const [modifiedStream] = modifiedInput.streams; + expect(modifiedStream.vars!.paths.value).toEqual(expect.arrayContaining(['north', 'south'])); + expect(modifiedStream.vars!.period.value).toEqual('12mo'); + }); + + it('should update elasticsearch.privileges.cluster when updating', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const mockPackagePolicy = createPackagePolicyMock(); + + const attributes = { + ...mockPackagePolicy, + inputs: [], + }; + (getPackageInfo as jest.Mock).mockImplementation(async (params) => { + return Promise.resolve({ + ...(await mockedGetPackageInfo(params)), + elasticsearch: { + privileges: { + cluster: ['monitor'], + }, + }, + } as PackageInfo); + }); + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes, + }, + ], + }); + + savedObjectsClient.bulkUpdate.mockImplementation( + async ( + objs: Array<{ + type: string; + id: string; + attributes: any; + }> + ) => { + const newObjs = objs.map((obj) => ({ + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes: obj.attributes, + })); + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: newObjs, + }); + return { + saved_objects: newObjs, + }; + } + ); + + const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + const result = await packagePolicyService.bulkUpdate( + savedObjectsClient, + elasticsearchClient, + [{ ...mockPackagePolicy, inputs: [] }] + ); + + expect(result![0].elasticsearch).toMatchObject({ privileges: { cluster: ['monitor'] } }); + }); + + it('should not mutate packagePolicyUpdate object when trimming whitespace', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const mockPackagePolicy = createPackagePolicyMock(); + + const attributes = { + ...mockPackagePolicy, + inputs: [], + }; + + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: [ + { + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes, + }, + ], + }); + + savedObjectsClient.bulkUpdate.mockImplementation( + async ( + objs: Array<{ + type: string; + id: string; + attributes: any; + }> + ) => { + const newObjs = objs.map((obj) => ({ + id: 'test', + type: 'abcd', + references: [], + version: 'test', + attributes: obj.attributes, + })); + savedObjectsClient.bulkGet.mockResolvedValue({ + saved_objects: newObjs, + }); + return { + saved_objects: newObjs, + }; + } + ); + + const elasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + const result = await packagePolicyService.bulkUpdate( + savedObjectsClient, + elasticsearchClient, + // this mimics the way that OSQuery plugin create immutable objects + [ + produce( + { ...mockPackagePolicy, name: ' test ', inputs: [] }, + (draft) => draft + ), + ] + ); + + expect(result![0].name).toEqual('test'); + }); + }); + describe('delete', () => { it('should allow to delete a package policy', async () => {}); }); diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 0dd16f51dac5f..4b4b9615009f3 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -542,32 +542,107 @@ class PackagePolicyClientImpl implements PackagePolicyClient { const newPolicy = (await this.get(soClient, id)) as PackagePolicy; - if (packagePolicy.package) { - await removeOldAssets({ - soClient, - pkgName: packagePolicy.package.name, - currentVersion: packagePolicy.package.version, - }); + await updatePackagePolicyVersion(packagePolicyUpdate, soClient, currentVersion); - if (packagePolicy.package.version !== currentVersion) { - const upgradeTelemetry: PackageUpdateEvent = { - packageName: packagePolicy.package.name, - currentVersion: currentVersion || 'unknown', - newVersion: packagePolicy.package.version, - status: 'success', - eventType: 'package-policy-upgrade' as UpdateEventType, - }; - sendTelemetryEvents( - appContextService.getLogger(), - appContextService.getTelemetryEventsSender(), - upgradeTelemetry - ); - appContextService.getLogger().info(`Package policy upgraded successfully`); - appContextService.getLogger().debug(JSON.stringify(upgradeTelemetry)); - } + return newPolicy; + } + + public async bulkUpdate( + soClient: SavedObjectsClientContract, + esClient: ElasticsearchClient, + packagePolicyUpdates: Array, + options?: { user?: AuthenticatedUser; force?: boolean }, + currentVersion?: string + ): Promise { + const oldPackagePolicies = await this.getByIDs( + soClient, + packagePolicyUpdates.map((p) => p.id) + ); + + if (!oldPackagePolicies || oldPackagePolicies.length === 0) { + throw new Error('Package policy not found'); } - return newPolicy; + const packageInfos = await getPackageInfoForPackagePolicies(packagePolicyUpdates, soClient); + + await soClient.bulkUpdate( + await pMap( + packagePolicyUpdates, + async (packagePolicyUpdate) => { + const id = packagePolicyUpdate.id; + const packagePolicy = { ...packagePolicyUpdate, name: packagePolicyUpdate.name.trim() }; + const oldPackagePolicy = oldPackagePolicies.find((p) => p.id === id); + if (!oldPackagePolicy) { + throw new Error('Package policy not found'); + } + + const { version, ...restOfPackagePolicy } = packagePolicy; + + if (packagePolicyUpdate.is_managed && !options?.force) { + throw new PackagePolicyRestrictionRelatedError(`Cannot update package policy ${id}`); + } + + let inputs = restOfPackagePolicy.inputs.map((input) => + assignStreamIdToInput(oldPackagePolicy.id, input) + ); + + inputs = enforceFrozenInputs(oldPackagePolicy.inputs, inputs, options?.force); + let elasticsearch: PackagePolicy['elasticsearch']; + if (packagePolicy.package?.name) { + const pkgInfo = packageInfos.get( + `${packagePolicy.package.name}-${packagePolicy.package.version}` + ); + if (pkgInfo) { + validatePackagePolicyOrThrow(packagePolicy, pkgInfo); + + inputs = await _compilePackagePolicyInputs(pkgInfo, packagePolicy.vars || {}, inputs); + elasticsearch = pkgInfo.elasticsearch; + } + } + + // Handle component template/mappings updates for experimental features, e.g. synthetic source + await handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, packagePolicy }); + + return { + type: SAVED_OBJECT_TYPE, + id, + attributes: { + ...restOfPackagePolicy, + inputs, + elasticsearch, + revision: oldPackagePolicy.revision + 1, + updated_at: new Date().toISOString(), + updated_by: options?.user?.username ?? 'system', + }, + version, + }; + }, + { concurrency: 50 } + ) + ); + + const agentPolicyIds = new Set(packagePolicyUpdates.map((p) => p.policy_id)); + + await pMap(agentPolicyIds, async (agentPolicyId) => { + // Bump revision of associated agent policy + await agentPolicyService.bumpRevision(soClient, esClient, agentPolicyId, { + user: options?.user, + }); + }); + + const newPolicies = await this.getByIDs( + soClient, + packagePolicyUpdates.map((p) => p.id) + ); + + await pMap( + packagePolicyUpdates, + async (packagePolicy) => + await updatePackagePolicyVersion(packagePolicy, soClient, currentVersion), + { concurrency: 50 } + ); + + return newPolicies; } public async delete( @@ -1768,6 +1843,37 @@ async function validateIsNotHostedPolicy( } } +export async function updatePackagePolicyVersion( + packagePolicy: (NewPackagePolicy & { version?: string; id: string }) | UpdatePackagePolicy, + soClient: SavedObjectsClientContract, + currentVersion?: string +) { + if (packagePolicy.package) { + await removeOldAssets({ + soClient, + pkgName: packagePolicy.package.name, + currentVersion: packagePolicy.package.version, + }); + + if (packagePolicy.package.version !== currentVersion) { + const upgradeTelemetry: PackageUpdateEvent = { + packageName: packagePolicy.package.name, + currentVersion: currentVersion || 'unknown', + newVersion: packagePolicy.package.version, + status: 'success', + eventType: 'package-policy-upgrade' as UpdateEventType, + }; + sendTelemetryEvents( + appContextService.getLogger(), + appContextService.getTelemetryEventsSender(), + upgradeTelemetry + ); + appContextService.getLogger().info(`Package policy upgraded successfully`); + appContextService.getLogger().debug(JSON.stringify(upgradeTelemetry)); + } + } +} + function deepMergeVars(original: any, override: any, keepOriginalValue = false): any { if (!original.vars) { original.vars = { ...override.vars }; diff --git a/x-pack/plugins/fleet/server/services/package_policy_service.ts b/x-pack/plugins/fleet/server/services/package_policy_service.ts index 36f19207bf107..4dd36a8c4fdf4 100644 --- a/x-pack/plugins/fleet/server/services/package_policy_service.ts +++ b/x-pack/plugins/fleet/server/services/package_policy_service.ts @@ -24,6 +24,7 @@ import type { import type { ExperimentalDataStreamFeature } from '../../common/types'; import type { NewPackagePolicy, UpdatePackagePolicy, PackagePolicy } from '../types'; import type { ExternalCallback } from '..'; + import type { NewPackagePolicyWithId } from './package_policy'; export interface PackagePolicyService { @@ -60,6 +61,14 @@ export interface PackagePolicyClient { } ): Promise; + bulkUpdate( + soClient: SavedObjectsClientContract, + esClient: ElasticsearchClient, + packagePolicyUpdates: Array, + options?: { user?: AuthenticatedUser; force?: boolean }, + currentVersion?: string + ): Promise; + get(soClient: SavedObjectsClientContract, id: string): Promise; findAllForAgentPolicy( diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/downsample.helpers.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/downsample.helpers.ts new file mode 100644 index 0000000000000..be96aaabe4a71 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/downsample.helpers.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { HttpSetup } from '@kbn/core/public'; +import { + createDownsampleActions, + createReadonlyActions, + createRolloverActions, + createSavePolicyAction, + createTogglePhaseAction, +} from '../../helpers'; +import { initTestBed } from '../init_test_bed'; +import { AppServicesContext } from '../../../../public/types'; + +type SetupReturn = ReturnType; + +export type DownsampleTestBed = SetupReturn extends Promise ? U : SetupReturn; + +export const setupDownsampleTestBed = async ( + httpSetup: HttpSetup, + args?: { + appServicesContext?: Partial; + } +) => { + const testBed = await initTestBed(httpSetup, args); + + return { + ...testBed, + actions: { + togglePhase: createTogglePhaseAction(testBed), + savePolicy: createSavePolicyAction(testBed), + ...createRolloverActions(testBed), + hot: { + ...createReadonlyActions(testBed, 'hot'), + ...createDownsampleActions(testBed, 'hot'), + }, + warm: { + ...createReadonlyActions(testBed, 'warm'), + ...createDownsampleActions(testBed, 'warm'), + }, + cold: { + ...createReadonlyActions(testBed, 'cold'), + ...createDownsampleActions(testBed, 'cold'), + }, + frozen: {}, + }, + }; +}; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/downsample.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/downsample.test.ts new file mode 100644 index 0000000000000..70aae4b44b987 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/downsample.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; +import { setupEnvironment } from '../../helpers'; +import { DownsampleTestBed, setupDownsampleTestBed } from './downsample.helpers'; + +describe(' downsample', () => { + let testBed: DownsampleTestBed; + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); + + beforeEach(async () => { + httpRequestsMockHelpers.setDefaultResponses(); + + await act(async () => { + testBed = await setupDownsampleTestBed(httpSetup); + }); + + const { component } = testBed; + component.update(); + + const { actions } = testBed; + await actions.rollover.toggleDefault(); + await actions.togglePhase('warm'); + await actions.togglePhase('cold'); + }); + + test('enabling downsample in hot should hide readonly in hot, warm and cold', async () => { + const { actions } = testBed; + + expect(actions.hot.readonlyExists()).toBeTruthy(); + expect(actions.warm.readonlyExists()).toBeTruthy(); + expect(actions.cold.readonlyExists()).toBeTruthy(); + + await actions.hot.downsample.toggle(); + + expect(actions.hot.readonlyExists()).toBeFalsy(); + expect(actions.warm.readonlyExists()).toBeFalsy(); + expect(actions.cold.readonlyExists()).toBeFalsy(); + }); + + test('enabling downsample in warm should hide readonly in warm and cold', async () => { + const { actions } = testBed; + + expect(actions.hot.readonlyExists()).toBeTruthy(); + expect(actions.warm.readonlyExists()).toBeTruthy(); + expect(actions.cold.readonlyExists()).toBeTruthy(); + + await actions.warm.downsample.toggle(); + + expect(actions.hot.readonlyExists()).toBeTruthy(); + expect(actions.warm.readonlyExists()).toBeFalsy(); + expect(actions.cold.readonlyExists()).toBeFalsy(); + }); + + test('enabling downsample in cold should hide readonly in cold', async () => { + const { actions } = testBed; + + expect(actions.hot.readonlyExists()).toBeTruthy(); + expect(actions.warm.readonlyExists()).toBeTruthy(); + expect(actions.cold.readonlyExists()).toBeTruthy(); + + await actions.cold.downsample.toggle(); + + expect(actions.hot.readonlyExists()).toBeTruthy(); + expect(actions.warm.readonlyExists()).toBeTruthy(); + expect(actions.cold.readonlyExists()).toBeFalsy(); + }); +}); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts index f4b41cedd70f1..e70f721a48075 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts @@ -7,6 +7,7 @@ import { HttpSetup } from '@kbn/core/public'; import { + createDownsampleActions, createForceMergeActions, createMinAgeActions, createReadonlyActions, @@ -41,16 +42,19 @@ export const setupSearchableSnapshotsTestBed = async ( ...createSearchableSnapshotActions(testBed, 'hot'), ...createForceMergeActions(testBed, 'hot'), ...createShrinkActions(testBed, 'hot'), + ...createDownsampleActions(testBed, 'hot'), }, warm: { ...createForceMergeActions(testBed, 'warm'), ...createShrinkActions(testBed, 'warm'), ...createReadonlyActions(testBed, 'warm'), + ...createDownsampleActions(testBed, 'warm'), }, cold: { ...createMinAgeActions(testBed, 'cold'), ...createSearchableSnapshotActions(testBed, 'cold'), ...createReadonlyActions(testBed, 'cold'), + ...createDownsampleActions(testBed, 'cold'), }, frozen: { ...createMinAgeActions(testBed, 'frozen'), diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts index 09bb8b85082b6..03b7670c1eac5 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts @@ -40,17 +40,21 @@ describe(' searchable snapshots', () => { expect(actions.warm.forceMergeExists()).toBeTruthy(); expect(actions.warm.shrinkExists()).toBeTruthy(); expect(actions.warm.readonlyExists()).toBeTruthy(); + expect(actions.warm.downsample.exists()).toBeTruthy(); expect(actions.cold.searchableSnapshotsExists()).toBeTruthy(); expect(actions.cold.readonlyExists()).toBeTruthy(); + expect(actions.cold.downsample.exists()).toBeTruthy(); await actions.hot.setSearchableSnapshot('my-repo'); expect(actions.warm.forceMergeExists()).toBeFalsy(); expect(actions.warm.shrinkExists()).toBeFalsy(); expect(actions.warm.readonlyExists()).toBeFalsy(); + expect(actions.warm.downsample.exists()).toBeFalsy(); // searchable snapshot in cold is still visible expect(actions.cold.searchableSnapshotsExists()).toBeTruthy(); expect(actions.cold.readonlyExists()).toBeFalsy(); + expect(actions.cold.downsample.exists()).toBeFalsy(); }); test('disabling rollover toggle, but enabling default rollover', async () => { diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts index 8ad72ca3d0a82..79f5fdc6e2840 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts @@ -12,7 +12,8 @@ import { PhaseWithDownsample } from '../../../../common/types'; import { setupEnvironment } from '../../helpers'; import { setupValidationTestBed, ValidationTestBed } from './validation.helpers'; -describe(' downsample interval validation', () => { +// FLAKY: https://github.com/elastic/kibana/issues/141160 +describe.skip(' downsample interval validation', () => { let testBed: ValidationTestBed; let actions: ValidationTestBed['actions']; const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts index 3e29bc5d76580..7db483d6d0ef2 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/timing.test.ts @@ -12,7 +12,8 @@ import { PhaseWithTiming } from '../../../../common/types'; import { setupEnvironment } from '../../helpers'; import { setupValidationTestBed, ValidationTestBed } from './validation.helpers'; -describe(' timing validation', () => { +// FLAKY: https://github.com/elastic/kibana/issues/115307 +describe.skip(' timing validation', () => { let testBed: ValidationTestBed; let actions: ValidationTestBed['actions']; const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts index 321a7efbfc5e3..983cfbadfa017 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts @@ -201,8 +201,6 @@ describe(' serialization', () => { await actions.hot.setShrinkCount('2'); await actions.hot.toggleReadonly(); await actions.hot.setIndexPriority('123'); - await actions.hot.downsample.toggle(); - await actions.hot.downsample.setDownsampleInterval('2', 'h'); await actions.savePolicy(); @@ -233,7 +231,6 @@ describe(' serialization', () => { priority: 123, }, readonly: {}, - downsample: { fixed_interval: '2h' }, }, }, }, @@ -257,6 +254,24 @@ describe(' serialization', () => { expect(parsedReqBody.phases.hot.actions.searchable_snapshot.snapshot_repository).toBe('abc'); }); + // Setting downsample disables setting readonly so we test this separately + test('setting downsample', async () => { + const { actions } = testBed; + + await actions.rollover.toggleDefault(); + await actions.hot.downsample.toggle(); + await actions.hot.downsample.setDownsampleInterval('2', 'h'); + + await actions.savePolicy(); + + const lastReq: HttpFetchOptionsWithPath[] = httpSetup.post.mock.calls.pop() || []; + const [requestUrl, requestBody] = lastReq; + const parsedReqBody = JSON.parse((requestBody as Record).body); + + expect(requestUrl).toBe(`${API_BASE_PATH}/policies`); + expect(parsedReqBody.phases.hot.actions.downsample).toEqual({ fixed_interval: '2h' }); + }); + test('disabling rollover', async () => { const { actions } = testBed; @@ -326,8 +341,6 @@ describe(' serialization', () => { await actions.warm.setBestCompression(true); await actions.warm.toggleReadonly(); await actions.warm.setIndexPriority('123'); - await actions.warm.downsample.toggle(); - await actions.warm.downsample.setDownsampleInterval('20', 'm'); await actions.savePolicy(); expect(httpSetup.post).toHaveBeenLastCalledWith( @@ -365,7 +378,6 @@ describe(' serialization', () => { number_of_replicas: 123, }, readonly: {}, - downsample: { fixed_interval: '20m' }, }, }, }, @@ -374,6 +386,25 @@ describe(' serialization', () => { ); }); + // Setting downsample disables setting readonly so we test this separately + test('setting downsample', async () => { + const { actions } = testBed; + + await actions.togglePhase('warm'); + await actions.warm.setMinAgeValue('11'); + await actions.warm.downsample.toggle(); + await actions.warm.downsample.setDownsampleInterval('20', 'm'); + + await actions.savePolicy(); + + const lastReq: HttpFetchOptionsWithPath[] = httpSetup.post.mock.calls.pop() || []; + const [requestUrl, requestBody] = lastReq; + const parsedReqBody = JSON.parse((requestBody as Record).body); + + expect(requestUrl).toBe(`${API_BASE_PATH}/policies`); + expect(parsedReqBody.phases.warm.actions.downsample).toEqual({ fixed_interval: '20m' }); + }); + describe('policy with include and exclude', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_INCLUDE_EXCLUDE]); @@ -469,8 +500,6 @@ describe(' serialization', () => { await actions.cold.setReplicas('123'); await actions.cold.toggleReadonly(); await actions.cold.setIndexPriority('123'); - await actions.cold.downsample.toggle(); - await actions.cold.downsample.setDownsampleInterval('5'); await actions.savePolicy(); @@ -502,7 +531,6 @@ describe(' serialization', () => { number_of_replicas: 123, }, readonly: {}, - downsample: { fixed_interval: '5d' }, }, }, }, @@ -511,6 +539,25 @@ describe(' serialization', () => { ); }); + // Setting downsample disables setting readonly so we test this separately + test('setting downsample', async () => { + const { actions } = testBed; + + await actions.togglePhase('cold'); + await actions.cold.setMinAgeValue('11'); + await actions.cold.downsample.toggle(); + await actions.cold.downsample.setDownsampleInterval('2'); + + await actions.savePolicy(); + + const lastReq: HttpFetchOptionsWithPath[] = httpSetup.post.mock.calls.pop() || []; + const [requestUrl, requestBody] = lastReq; + const parsedReqBody = JSON.parse((requestBody as Record).body); + + expect(requestUrl).toBe(`${API_BASE_PATH}/policies`); + expect(parsedReqBody.phases.cold.actions.downsample).toEqual({ fixed_interval: '2d' }); + }); + // Setting searchable snapshot field disables setting replicas so we test this separately test('setting searchable snapshot', async () => { const { actions } = testBed; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx index e3214eab3ec47..dd983f336a224 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -30,17 +30,25 @@ const i18nTexts = { }; export const ColdPhase: FunctionComponent = () => { - const { isUsingSearchableSnapshotInHotPhase } = useConfiguration(); + const { + isUsingSearchableSnapshotInHotPhase, + isUsingDownsampleInHotPhase, + isUsingDownsampleInWarmPhase, + isUsingDownsampleInColdPhase, + } = useConfiguration(); return ( }> - {/* Readonly section */} - {!isUsingSearchableSnapshotInHotPhase && } - {!isUsingSearchableSnapshotInHotPhase && } + {/* Readonly section */} + {!isUsingSearchableSnapshotInHotPhase && + !isUsingDownsampleInHotPhase && + !isUsingDownsampleInWarmPhase && + !isUsingDownsampleInColdPhase && } + {/* Data tier allocation section */} { const [formData] = useFormData({ watch: [isUsingDefaultRolloverPath, ...rolloverFieldPaths], }); - const { isUsingRollover } = useConfiguration(); + const { isUsingRollover, isUsingDownsampleInHotPhase } = useConfiguration(); const isUsingDefaultRollover: boolean = get(formData, isUsingDefaultRolloverPath); const showEmptyRolloverFieldsError = useRolloverValueRequiredValidation(); @@ -176,8 +176,8 @@ export const HotPhase: FunctionComponent = () => { {} {license.canUseSearchableSnapshot() && } - + {!isUsingDownsampleInHotPhase && } )} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx index fba9556b5f4ea..af69a388cd747 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx @@ -31,7 +31,11 @@ const i18nTexts = { }; export const WarmPhase: FunctionComponent = () => { - const { isUsingSearchableSnapshotInHotPhase } = useConfiguration(); + const { + isUsingSearchableSnapshotInHotPhase, + isUsingDownsampleInHotPhase, + isUsingDownsampleInWarmPhase, + } = useConfiguration(); return ( @@ -41,10 +45,12 @@ export const WarmPhase: FunctionComponent = () => { {!isUsingSearchableSnapshotInHotPhase && } - {!isUsingSearchableSnapshotInHotPhase && } - {!isUsingSearchableSnapshotInHotPhase && } + {!isUsingSearchableSnapshotInHotPhase && + !isUsingDownsampleInHotPhase && + !isUsingDownsampleInWarmPhase && } + {/* Data tier allocation section */} + `_meta.${phase}.downsample.enabled`; + /** * These strings describe the path to their respective values in the serialized * ILM form. diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx index 5d506d6235f3f..63dfaeed57e9f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx @@ -10,7 +10,11 @@ import React, { FunctionComponent, createContext, useContext } from 'react'; import { useFormData } from '../../../../shared_imports'; -import { isUsingDefaultRolloverPath, isUsingCustomRolloverPath } from '../constants'; +import { + isUsingDefaultRolloverPath, + isUsingCustomRolloverPath, + isUsingDownsamplePath, +} from '../constants'; export interface Configuration { /** @@ -26,6 +30,14 @@ export interface Configuration { */ isUsingSearchableSnapshotInHotPhase: boolean; isUsingSearchableSnapshotInColdPhase: boolean; + + /** + * When downsample enabled it implicitly makes index readonly, + * We should hide readonly action if downsample is enabled + */ + isUsingDownsampleInHotPhase: boolean; + isUsingDownsampleInWarmPhase: boolean; + isUsingDownsampleInColdPhase: boolean; } const ConfigurationContext = createContext(null as any); @@ -43,6 +55,9 @@ export const ConfigurationProvider: FunctionComponent = ({ children }) => { pathToColdPhaseSearchableSnapshot, isUsingCustomRolloverPath, isUsingDefaultRolloverPath, + isUsingDownsamplePath('hot'), + isUsingDownsamplePath('warm'), + isUsingDownsamplePath('cold'), ], }); const isUsingDefaultRollover = get(formData, isUsingDefaultRolloverPath); @@ -53,6 +68,9 @@ export const ConfigurationProvider: FunctionComponent = ({ children }) => { isUsingRollover: isUsingDefaultRollover === false ? isUsingCustomRollover : true, isUsingSearchableSnapshotInHotPhase: get(formData, pathToHotPhaseSearchableSnapshot) != null, isUsingSearchableSnapshotInColdPhase: get(formData, pathToColdPhaseSearchableSnapshot) != null, + isUsingDownsampleInHotPhase: !!get(formData, isUsingDownsamplePath('hot')), + isUsingDownsampleInWarmPhase: !!get(formData, isUsingDownsamplePath('warm')), + isUsingDownsampleInColdPhase: !!get(formData, isUsingDownsamplePath('cold')), }; return {children}; diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index 62568a3cbca5e..6aa7bef84d3e2 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -203,7 +203,7 @@ export async function mountApp( }); } }; - // get state from location, used for nanigating from Visualize/Discover to Lens + // get state from location, used for navigating from Visualize/Discover to Lens const initialContext = historyLocationState && (historyLocationState.type === ACTION_VISUALIZE_LENS_FIELD || diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts index 26c60127b693b..c886c21cfa6b8 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts @@ -13,6 +13,7 @@ import { difference } from 'lodash'; import type { DataViewsContract, DataViewSpec } from '@kbn/data-views-plugin/public'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { DataViewPersistableStateService } from '@kbn/data-views-plugin/common'; +import { isAnnotationsLayer } from '@kbn/visualizations-plugin/common/convert_to_lens'; import { Datasource, DatasourceLayers, @@ -53,6 +54,9 @@ function getIndexPatterns( for (const { indexPatternId } of initialContext.layers) { indexPatternIds.push(indexPatternId); } + for (const l of initialContext.configuration.layers) { + if (isAnnotationsLayer(l)) indexPatternIds.push(l.indexPatternId); + } } else { indexPatternIds.push(initialContext.dataViewSpec.id!); } @@ -209,6 +213,7 @@ export async function initializeSources( visualizationMap, visualizationState, references, + initialContext, }), }; } @@ -217,16 +222,19 @@ export function initializeVisualization({ visualizationMap, visualizationState, references, + initialContext, }: { visualizationState: VisualizationState; visualizationMap: VisualizationMap; references?: SavedObjectReference[]; + initialContext?: VisualizeFieldContext | VisualizeEditorContext; }) { if (visualizationState?.activeId) { return ( visualizationMap[visualizationState.activeId]?.fromPersistableState?.( visualizationState.state, - references + references, + initialContext ) ?? visualizationState.state ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index 9c0e87e4a1464..9acec09776207 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -312,12 +312,12 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ const visualizeGeoFieldTrigger = uiActions.getTrigger(VISUALIZE_GEO_FIELD_TRIGGER); const allFields = useMemo( () => - visualizeGeoFieldTrigger && currentIndexPattern.isPersisted + visualizeGeoFieldTrigger ? currentIndexPattern.fields : currentIndexPattern.fields.filter( ({ type }) => type !== 'geo_point' && type !== 'geo_shape' ), - [currentIndexPattern.fields, currentIndexPattern.isPersisted, visualizeGeoFieldTrigger] + [currentIndexPattern.fields, visualizeGeoFieldTrigger] ); const clearLocalState = () => setLocalState((s) => ({ ...s, nameFilter: '', typeFilter: [] })); const availableFieldTypes = uniq([ diff --git a/x-pack/plugins/lens/public/state_management/fullscreen_middleware.ts b/x-pack/plugins/lens/public/state_management/fullscreen_middleware.ts index f125a9e830ec9..e52c3d312802b 100644 --- a/x-pack/plugins/lens/public/state_management/fullscreen_middleware.ts +++ b/x-pack/plugins/lens/public/state_management/fullscreen_middleware.ts @@ -12,10 +12,10 @@ import { setToggleFullscreen } from './lens_slice'; /** cancels updates to the store that don't change the state */ export const fullscreenMiddleware = (storeDeps: LensStoreDeps) => (store: MiddlewareAPI) => { return (next: Dispatch) => (action: Action) => { - next(action); if (setToggleFullscreen.match(action)) { const isFullscreen = (store.getState as LensGetState)().lens.isFullscreenDatasource; - storeDeps.lensServices.chrome.setIsVisible(!isFullscreen); + storeDeps.lensServices.chrome.setIsVisible(Boolean(isFullscreen)); } + next(action); }; }; diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index b49149b92317b..e581064bcdbf2 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -917,7 +917,11 @@ export interface Visualization { /** Visualizations can have references as well */ getPersistableState?: (state: T) => { state: P; savedObjectReferences: SavedObjectReference[] }; /** Hydrate from persistable state and references to final state */ - fromPersistableState?: (state: P, references?: SavedObjectReference[]) => T; + fromPersistableState?: ( + state: P, + references?: SavedObjectReference[], + initialContext?: VisualizeFieldContext | VisualizeEditorContext + ) => T; /** Frame needs to know which layers the visualization is currently using */ getLayerIds: (state: T) => string[]; /** Reset button on each layer triggers this */ diff --git a/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts b/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts index d683888a88cfd..a84168b009f9e 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/state_helpers.ts @@ -10,11 +10,13 @@ import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; import type { SavedObjectReference } from '@kbn/core/public'; import { isQueryAnnotationConfig } from '@kbn/event-annotation-plugin/public'; import { i18n } from '@kbn/i18n'; +import { VisualizeFieldContext } from '@kbn/ui-actions-plugin/public'; import { validateQuery } from '../../shared_components'; import type { FramePublicAPI, DatasourcePublicAPI, VisualizationDimensionGroupConfig, + VisualizeEditorContext, } from '../../types'; import { visualizationTypes, @@ -26,6 +28,7 @@ import { XYState, XYPersistedState, State, + XYAnnotationLayerConfig, } from './types'; import { getDataLayers, isAnnotationsLayer, isDataLayer } from './visualization_helpers'; @@ -140,11 +143,13 @@ export function extractReferences(state: XYState) { export function injectReferences( state: XYPersistedState, - references?: SavedObjectReference[] + references?: SavedObjectReference[], + initialContext?: VisualizeFieldContext | VisualizeEditorContext ): XYState { if (!references || !references.length) { return state as XYState; } + const fallbackIndexPatternId = references.find(({ type }) => type === 'index-pattern')!.id; return { ...state, @@ -155,6 +160,7 @@ export function injectReferences( return { ...layer, indexPatternId: + getIndexPatternIdFromInitialContext(layer, initialContext) || references.find(({ name }) => name === getLayerReferenceName(layer.layerId))?.id || fallbackIndexPatternId, }; @@ -162,6 +168,15 @@ export function injectReferences( }; } +function getIndexPatternIdFromInitialContext( + layer: XYAnnotationLayerConfig, + initialContext?: VisualizeFieldContext | VisualizeEditorContext +) { + if (initialContext && 'isVisualizeAction' in initialContext) { + return layer && 'indexPatternId' in layer ? layer.indexPatternId : undefined; + } +} + export function validateColumn( state: State, frame: Pick, diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx index 64ffbab4c38e7..61bdd4151219c 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx @@ -184,8 +184,8 @@ export const getXyVisualization = ({ return extractReferences(state); }, - fromPersistableState(state, references) { - return injectReferences(state, references); + fromPersistableState(state, references, initialContext) { + return injectReferences(state, references, initialContext); }, getDescription, diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/icon_set.ts b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/icon_set.ts index 23a4b6fb52610..45019dd204491 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/icon_set.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/icon_set.ts @@ -82,6 +82,12 @@ export const annotationsIconSet: IconSet = [ value: 'starEmpty', label: i18n.translate('xpack.lens.xyChart.iconSelect.starLabel', { defaultMessage: 'Star' }), }, + { + value: 'starFilled', + label: i18n.translate('xpack.lens.xyChart.iconSelect.starFilledLabel', { + defaultMessage: 'Star filled', + }), + }, { value: 'tag', label: i18n.translate('xpack.lens.xyChart.iconSelect.tagIconLabel', { diff --git a/x-pack/plugins/maps/common/migrations/migrate_data_view_persisted_state.test.ts b/x-pack/plugins/maps/common/migrations/migrate_data_view_persisted_state.test.ts new file mode 100644 index 0000000000000..e46ad2e77304a --- /dev/null +++ b/x-pack/plugins/maps/common/migrations/migrate_data_view_persisted_state.test.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Serializable } from '@kbn/utility-types'; +import { migrateDataViewsPersistedState } from './migrate_data_view_persisted_state'; + +const migrationMock = (spec: Serializable): Serializable => { + return { + ...(spec as unknown as Record), + newProp: 'somethingThatChanged', + } as unknown as Serializable; +}; + +test('should apply data view migrations to adhoc data view specs', () => { + const attributes = { + title: 'My map', + mapStateJSON: JSON.stringify({ + adHocDataViews: [{ id: 'myAdHocDataView' }], + }), + }; + const { mapStateJSON } = migrateDataViewsPersistedState({ attributes }, migrationMock); + expect(JSON.parse(mapStateJSON!)).toEqual({ + adHocDataViews: [{ id: 'myAdHocDataView', newProp: 'somethingThatChanged' }], + }); +}); diff --git a/x-pack/plugins/maps/common/migrations/migrate_data_view_persisted_state.ts b/x-pack/plugins/maps/common/migrations/migrate_data_view_persisted_state.ts new file mode 100644 index 0000000000000..413afbdc245b9 --- /dev/null +++ b/x-pack/plugins/maps/common/migrations/migrate_data_view_persisted_state.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Serializable } from '@kbn/utility-types'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; +import { MigrateFunction } from '@kbn/kibana-utils-plugin/common'; +import { MapSavedObjectAttributes } from '../map_saved_object_type'; + +export function migrateDataViewsPersistedState( + { + attributes, + }: { + attributes: MapSavedObjectAttributes; + }, + migration: MigrateFunction +): MapSavedObjectAttributes { + let mapState: { adHocDataViews?: DataViewSpec[] } = { adHocDataViews: [] }; + if (attributes.mapStateJSON) { + try { + mapState = JSON.parse(attributes.mapStateJSON); + } catch (e) { + throw new Error('Unable to parse attribute mapStateJSON'); + } + + if (mapState.adHocDataViews && mapState.adHocDataViews.length > 0) { + mapState.adHocDataViews = mapState.adHocDataViews.map((spec) => { + return migration(spec) as unknown as DataViewSpec; + }); + } + } + + return { + ...attributes, + mapStateJSON: JSON.stringify(mapState), + }; +} diff --git a/x-pack/plugins/maps/common/migrations/references.test.ts b/x-pack/plugins/maps/common/migrations/references.test.ts index 5b749022bb62b..e7f62bd866fbb 100644 --- a/x-pack/plugins/maps/common/migrations/references.test.ts +++ b/x-pack/plugins/maps/common/migrations/references.test.ts @@ -42,6 +42,21 @@ describe('extractReferences', () => { }); }); + test('Should handle mapStateJSON without adHocDataViews', () => { + const mapStateJSON = JSON.stringify({}); + const attributes = { + title: 'my map', + mapStateJSON, + }; + expect(extractReferences({ attributes })).toEqual({ + attributes: { + title: 'my map', + mapStateJSON, + }, + references: [], + }); + }); + test('Should extract index-pattern reference from ES search source descriptor', () => { const attributes = { title: 'my map', @@ -62,6 +77,30 @@ describe('extractReferences', () => { }); }); + test('Should ignore adhoc data view reference from search source', () => { + const mapStateJSON = JSON.stringify({ + adHocDataViews: [ + { + id: 'c698b940-e149-11e8-a35a-370a8516603a', + }, + ], + }); + + const attributes = { + title: 'my map', + layerListJSON: layerListJSON.esSearchSource.withIndexPatternId, + mapStateJSON, + }; + expect(extractReferences({ attributes })).toEqual({ + attributes: { + title: 'my map', + layerListJSON: layerListJSON.esSearchSource.withIndexPatternId, + mapStateJSON, + }, + references: [], + }); + }); + test('Should extract index-pattern reference from ES geo grid source descriptor', () => { const attributes = { title: 'my map', @@ -121,6 +160,29 @@ describe('extractReferences', () => { ], }); }); + + test('Should ignore adhoc data view reference from joins', () => { + const mapStateJSON = JSON.stringify({ + adHocDataViews: [ + { + id: 'e20b2a30-f735-11e8-8ce0-9723965e01e3', + }, + ], + }); + const attributes = { + title: 'my map', + layerListJSON: layerListJSON.join.withIndexPatternId, + mapStateJSON, + }; + expect(extractReferences({ attributes })).toEqual({ + attributes: { + title: 'my map', + layerListJSON: layerListJSON.join.withIndexPatternId, + mapStateJSON, + }, + references: [], + }); + }); }); describe('injectReferences', () => { diff --git a/x-pack/plugins/maps/common/migrations/references.ts b/x-pack/plugins/maps/common/migrations/references.ts index 944789445fa06..fc94236583470 100644 --- a/x-pack/plugins/maps/common/migrations/references.ts +++ b/x-pack/plugins/maps/common/migrations/references.ts @@ -7,6 +7,7 @@ // Can not use public Layer classes to extract references since this logic must run in both client and server. +import type { DataViewSpec } from '@kbn/data-plugin/common'; import { SavedObjectReference } from '@kbn/core/types'; import { MapSavedObjectAttributes } from '../map_saved_object_type'; import { LayerDescriptor, VectorLayerDescriptor } from '../descriptor_types'; @@ -27,6 +28,22 @@ export function extractReferences({ return { attributes, references }; } + const adhocDataViewIds: string[] = []; + if (attributes.mapStateJSON) { + try { + const mapState = JSON.parse(attributes.mapStateJSON); + if (mapState.adHocDataViews && mapState.adHocDataViews.length > 0) { + (mapState.adHocDataViews as DataViewSpec[]).forEach((spec) => { + if (spec.id) { + adhocDataViewIds.push(spec.id); + } + }); + } + } catch (e) { + throw new Error('Unable to parse attribute mapStateJSON'); + } + } + const extractedReferences: SavedObjectReference[] = []; let layerList: LayerDescriptor[] = []; @@ -38,7 +55,13 @@ export function extractReferences({ layerList.forEach((layer, layerIndex) => { // Extract index-pattern references from source descriptor - if (layer.sourceDescriptor && 'indexPatternId' in layer.sourceDescriptor) { + if ( + layer.sourceDescriptor && + 'indexPatternId' in layer.sourceDescriptor && + !adhocDataViewIds.includes( + (layer.sourceDescriptor as IndexPatternReferenceDescriptor).indexPatternId! + ) + ) { const sourceDescriptor = layer.sourceDescriptor as IndexPatternReferenceDescriptor; const refName = `layer_${layerIndex}_source_index_pattern`; extractedReferences.push({ @@ -55,7 +78,12 @@ export function extractReferences({ const vectorLayer = layer as VectorLayerDescriptor; const joins = vectorLayer.joins ? vectorLayer.joins : []; joins.forEach((join, joinIndex) => { - if ('indexPatternId' in join.right) { + if ( + 'indexPatternId' in join.right && + !adhocDataViewIds.includes( + (join.right as IndexPatternReferenceDescriptor).indexPatternId! + ) + ) { const sourceDescriptor = join.right as IndexPatternReferenceDescriptor; const refName = `layer_${layerIndex}_join_${joinIndex}_index_pattern`; extractedReferences.push({ diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts b/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts index 6f823f218ca23..3642448774c58 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { first } from 'rxjs/operators'; import { i18n } from '@kbn/i18n'; import { EmbeddableFactoryDefinition, IContainer } from '@kbn/embeddable-plugin/public'; import { MAP_SAVED_OBJECT_TYPE, APP_ICON } from '../../common/constants'; @@ -12,6 +13,7 @@ import { getMapEmbeddableDisplayName } from '../../common/i18n_getters'; import { extract, inject } from '../../common/embeddable'; import { MapByReferenceInput, MapEmbeddableInput } from './types'; import { lazyLoadMapModules } from '../lazy_load_bundle'; +import { getApplication, getUsageCollection } from '../kibana_services'; export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { type = MAP_SAVED_OBJECT_TYPE; @@ -50,6 +52,15 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { create = async (input: MapEmbeddableInput, parent?: IContainer) => { const { MapEmbeddable } = await lazyLoadMapModules(); + const usageCollection = getUsageCollection(); + if (usageCollection) { + // currentAppId$ is a BehaviorSubject exposed as an observable so subscription gets last value upon subscribe + getApplication() + .currentAppId$.pipe(first()) + .subscribe((appId) => { + if (appId) usageCollection.reportUiCounter('map', 'loaded', `open_maps_vis_${appId}`); + }); + } return new MapEmbeddable( { editable: await this.isEditable(), diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index 41f88de18720c..a1a8a19674a81 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -66,6 +66,7 @@ export const getPresentationUtilContext = () => pluginsStart.presentationUtil.Co export const getSecurityService = () => pluginsStart.security; export const getSpacesApi = () => pluginsStart.spaces; export const getTheme = () => coreStart.theme; +export const getApplication = () => coreStart.application; export const getUsageCollection = () => pluginsStart.usageCollection; export const isScreenshotMode = () => { return pluginsStart.screenshotMode ? pluginsStart.screenshotMode.isScreenshotMode() : false; diff --git a/x-pack/plugins/maps/public/locators.ts b/x-pack/plugins/maps/public/locators.ts index 92749605efbb1..c4d7bb6f3d6bb 100644 --- a/x-pack/plugins/maps/public/locators.ts +++ b/x-pack/plugins/maps/public/locators.ts @@ -8,6 +8,7 @@ /* eslint-disable max-classes-per-file */ import rison from 'rison-node'; +import type { DataViewSpec } from '@kbn/data-views-plugin/public'; import type { SerializableRecord } from '@kbn/utility-types'; import { type Filter, isFilterPinned, type TimeRange, type Query } from '@kbn/es-query'; import type { GlobalQueryStateFromUrl, RefreshInterval } from '@kbn/data-plugin/public'; @@ -55,6 +56,11 @@ export interface MapsAppLocatorParams extends SerializableRecord { * whether to hash the data in the url to avoid url length issues. */ hash?: boolean; + + /** + * Optionally pass adhoc data view spec. + */ + dataViewSpec?: DataViewSpec; } export const MAPS_APP_LOCATOR = 'MAPS_APP_LOCATOR' as const; @@ -104,7 +110,11 @@ export class MapsAppLocatorDefinition implements LocatorDefinition { }; async _initMap() { + // Handle redirect with adhoc data view spec provided via history location state (MAPS_APP_LOCATOR) + const historyLocationState = this.props.history.location?.state as + | { + dataViewSpec: DataViewSpec; + } + | undefined; + if (historyLocationState?.dataViewSpec?.id) { + const dataViewService = getIndexPatternService(); + try { + const dataView = await dataViewService.get(historyLocationState.dataViewSpec.id); + if (!dataView.isPersisted()) { + await dataViewService.create(historyLocationState.dataViewSpec); + } + } catch (error) { + // ignore errors, not a critical error for viewing map - layer(s) using data view will surface error + } + } + try { await this.props.savedMap.whenReady(); } catch (err) { diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts index 181fe6c56e1ef..e7adcd0795efb 100644 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts +++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts @@ -19,6 +19,7 @@ import { getMapZoom, getMapCenter, getLayerListRaw, + getLayerList, getQuery, getFilters, getMapSettings, @@ -37,6 +38,7 @@ import { getMapAttributeService, SharingSavedObjectProps } from '../../../map_at import { MapByReferenceInput, MapEmbeddableInput } from '../../../embeddable/types'; import { getCoreChrome, + getIndexPatternService, getToasts, getIsAllowByValueEmbeddables, getSavedObjectsTagging, @@ -53,6 +55,7 @@ import { whenLicenseInitialized } from '../../../licensed_features'; import { SerializedMapState, SerializedUiState } from './types'; import { setAutoOpenLayerWizardId } from '../../../actions/ui_actions'; import { LayerStatsCollector, MapSettingsCollector } from '../../../../common/telemetry'; +import { getIndexPatternsFromIds } from '../../../index_pattern_util'; function setMapSettingsFromEncodedState(settings: Partial) { const decodedCustomIcons = settings.customIcons @@ -141,6 +144,21 @@ export class SavedMap { this._reportUsage(); + if (this._attributes?.mapStateJSON) { + try { + const mapState = JSON.parse(this._attributes.mapStateJSON) as SerializedMapState; + if (mapState.adHocDataViews && mapState.adHocDataViews.length > 0) { + const dataViewService = getIndexPatternService(); + const promises = mapState.adHocDataViews.map((spec) => { + return dataViewService.create(spec); + }); + await Promise.all(promises); + } + } catch (e) { + // ignore malformed mapStateJSON, not a critical error for viewing map - map will just use defaults + } + } + if (this._mapEmbeddableInput && this._mapEmbeddableInput.mapSettings !== undefined) { this._store.dispatch(setMapSettingsFromEncodedState(this._mapEmbeddableInput.mapSettings)); } else if (this._attributes?.mapStateJSON) { @@ -433,7 +451,7 @@ export class SavedMap { if (newTags) { this._tags = newTags; } - this._syncAttributesWithStore(); + await this._syncAttributesWithStore(); let updatedMapEmbeddableInput: MapEmbeddableInput; try { @@ -517,7 +535,7 @@ export class SavedMap { return; } - private _syncAttributesWithStore() { + private async _syncAttributesWithStore() { const state: MapStoreState = this._store.getState(); const layerList = getLayerListRaw(state); const layerListConfigOnly = copyPersistentState(layerList); @@ -526,6 +544,7 @@ export class SavedMap { const mapSettings = getMapSettings(state); this._attributes!.mapStateJSON = JSON.stringify({ + adHocDataViews: await this._getAdHocDataViews(), zoom: getMapZoom(state), center: getMapCenter(state), timeFilters: getTimeFilters(state), @@ -549,4 +568,20 @@ export class SavedMap { openTOCDetails: getOpenTOCDetails(state), } as SerializedUiState); } + + private async _getAdHocDataViews() { + const dataViewIds: string[] = []; + getLayerList(this._store.getState()).forEach((layer) => { + dataViewIds.push(...layer.getIndexPatternIds()); + }); + + const dataViews = await getIndexPatternsFromIds(_.uniq(dataViewIds)); + return dataViews + .filter((dataView) => { + return !dataView.isPersisted(); + }) + .map((dataView) => { + return dataView.toSpec(false); + }); + } } diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/types.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/types.ts index b20bcad980e72..28568e8610da0 100644 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/types.ts +++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { Query } from '@kbn/data-plugin/common'; +import type { DataViewSpec, Query } from '@kbn/data-plugin/common'; import { Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; import { MapCenter, MapSettings } from '../../../../common/descriptor_types'; @@ -17,6 +17,7 @@ export interface RefreshConfig { // parsed contents of mapStateJSON export interface SerializedMapState { + adHocDataViews?: DataViewSpec[]; zoom: number; center: MapCenter; timeFilters?: TimeRange; diff --git a/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts b/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts index f073c7335eb09..55983a54a61a3 100644 --- a/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts +++ b/x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts @@ -90,6 +90,7 @@ const getMapsLink = async (context: VisualizeFieldContext) => { query: getData().query.queryString.getQuery() as Query, initialLayers: initialLayers as unknown as LayerDescriptor[] & SerializableRecord, timeRange: getData().query.timefilter.timefilter.getTime(), + dataViewSpec: context.dataViewSpec, }); return location; diff --git a/x-pack/plugins/maps/server/embeddable/setup_embeddable.ts b/x-pack/plugins/maps/server/embeddable/setup_embeddable.ts index 68ecc70df0e9e..eefc67ac9318e 100644 --- a/x-pack/plugins/maps/server/embeddable/setup_embeddable.ts +++ b/x-pack/plugins/maps/server/embeddable/setup_embeddable.ts @@ -13,18 +13,22 @@ import { import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; import { extract, inject } from '../../common/embeddable'; import { embeddableMigrations } from './embeddable_migrations'; -import { getPersistedStateMigrations } from '../saved_objects'; +import { getMapsFilterMigrations, getMapsDataViewMigrations } from '../saved_objects'; export function setupEmbeddable( embeddable: EmbeddableSetup, - getFilterMigrations: () => MigrateFunctionsObject + getFilterMigrations: () => MigrateFunctionsObject, + getDataViewMigrations: () => MigrateFunctionsObject ) { embeddable.registerEmbeddableFactory({ id: MAP_SAVED_OBJECT_TYPE, migrations: () => { return mergeMigrationFunctionMaps( - embeddableMigrations, - getPersistedStateMigrations(getFilterMigrations()) + mergeMigrationFunctionMaps( + embeddableMigrations, + getMapsFilterMigrations(getFilterMigrations()) + ), + getMapsDataViewMigrations(getDataViewMigrations()) ); }, inject, diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 8101018c6db6f..838b6c3cc7ef5 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -15,6 +15,7 @@ import { DEFAULT_APP_CATEGORIES, } from '@kbn/core/server'; import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; +import { DataViewPersistableStateService } from '@kbn/data-views-plugin/common'; import type { EMSSettings } from '@kbn/maps-ems-plugin/server'; // @ts-expect-error import { getEcommerceSavedObjects } from './sample_data/ecommerce_saved_objects'; @@ -148,6 +149,9 @@ export class MapsPlugin implements Plugin { const getFilterMigrations = plugins.data.query.filterManager.getAllMigrations.bind( plugins.data.query.filterManager ); + const getDataViewMigrations = DataViewPersistableStateService.getAllMigrations.bind( + DataViewPersistableStateService + ); const { usageCollection, home, features, customIntegrations } = plugins; const config$ = this._initializerContext.config.create(); @@ -195,10 +199,10 @@ export class MapsPlugin implements Plugin { }, }); - setupSavedObjects(core, getFilterMigrations); + setupSavedObjects(core, getFilterMigrations, getDataViewMigrations); registerMapsUsageCollector(usageCollection); - setupEmbeddable(plugins.embeddable, getFilterMigrations); + setupEmbeddable(plugins.embeddable, getFilterMigrations, getDataViewMigrations); return { config: config$, diff --git a/x-pack/plugins/maps/server/saved_objects/index.ts b/x-pack/plugins/maps/server/saved_objects/index.ts index 1b0b129a29299..2cf9a1144ac27 100644 --- a/x-pack/plugins/maps/server/saved_objects/index.ts +++ b/x-pack/plugins/maps/server/saved_objects/index.ts @@ -5,4 +5,8 @@ * 2.0. */ -export { getPersistedStateMigrations, setupSavedObjects } from './setup_saved_objects'; +export { + getMapsDataViewMigrations, + getMapsFilterMigrations, + setupSavedObjects, +} from './setup_saved_objects'; diff --git a/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts b/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts index caa99d98662c1..c75f1f322e25c 100644 --- a/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts +++ b/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts @@ -12,12 +12,14 @@ import { MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; import { mergeSavedObjectMigrationMaps } from '@kbn/core/server'; import { APP_ICON, getFullPath } from '../../common/constants'; import { migrateDataPersistedState } from '../../common/migrations/migrate_data_persisted_state'; +import { migrateDataViewsPersistedState } from '../../common/migrations/migrate_data_view_persisted_state'; import type { MapSavedObjectAttributes } from '../../common/map_saved_object_type'; import { savedObjectMigrations } from './saved_object_migrations'; export function setupSavedObjects( core: CoreSetup, - getFilterMigrations: () => MigrateFunctionsObject + getFilterMigrations: () => MigrateFunctionsObject, + getDataViewMigrations: () => MigrateFunctionsObject ) { core.savedObjects.registerType({ name: 'map', @@ -51,8 +53,11 @@ export function setupSavedObjects( }, migrations: () => { return mergeSavedObjectMigrationMaps( - savedObjectMigrations, - getPersistedStateMigrations(getFilterMigrations()) as unknown as SavedObjectMigrationMap + mergeSavedObjectMigrationMaps( + savedObjectMigrations, + getMapsFilterMigrations(getFilterMigrations()) as unknown as SavedObjectMigrationMap + ), + getMapsDataViewMigrations(getDataViewMigrations()) ); }, }); @@ -76,9 +81,9 @@ export function setupSavedObjects( } /** - * This creates a migration map that applies external plugin migrations to persisted state stored in Maps + * This creates a migration map that applies external data plugin migrations to persisted filter state stored in Maps */ -export const getPersistedStateMigrations = ( +export const getMapsFilterMigrations = ( filterMigrations: MigrateFunctionsObject ): MigrateFunctionsObject => mapValues( @@ -98,3 +103,27 @@ export const getPersistedStateMigrations = ( } } ); + +/** + * This creates a migration map that applies external data view plugin migrations to persisted data view state stored in Maps + */ +export const getMapsDataViewMigrations = ( + migrations: MigrateFunctionsObject +): MigrateFunctionsObject => + mapValues( + migrations, + (migration) => (doc: SavedObjectUnsanitizedDoc) => { + try { + const attributes = migrateDataViewsPersistedState(doc, migration); + + return { + ...doc, + attributes, + }; + } catch (e) { + // Do not fail migration + // Maps application can display error when saved object is viewed + return doc; + } + } + ); diff --git a/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx b/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx index f5d842d5d7493..2e2444fff853b 100644 --- a/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx @@ -93,19 +93,14 @@ export const AnomalyDetectionTable: FC = ({ items, statsBarData, chartsSe if (!swimLaneData) return null; - const hasResults = swimLaneData.points.length > 0; - - const noDatWarning = hasResults ? ( - - ) : ( - - ); + if (swimLaneData.points.length > 0 && swimLaneData.points.every((v) => v.value === 0)) { + return ( + + ); + } return ( = ({ items, statsBarData, chartsSe showTimeline={false} showYAxis={false} showLegend={false} - noDataWarning={noDatWarning} + noDataWarning={ + + } chartsService={chartsService} /> ); diff --git a/x-pack/plugins/monitoring/public/application/pages/page_template.tsx b/x-pack/plugins/monitoring/public/application/pages/page_template.tsx index c67ea0df8a180..8912b38f57a20 100644 --- a/x-pack/plugins/monitoring/public/application/pages/page_template.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/page_template.tsx @@ -148,7 +148,11 @@ export const PageTemplate: React.FC = ({ })} )} - {renderContent()} + + + {renderContent()} + + diff --git a/x-pack/plugins/observability/common/index.ts b/x-pack/plugins/observability/common/index.ts index 78262d806bb46..e4a36b379ff49 100644 --- a/x-pack/plugins/observability/common/index.ts +++ b/x-pack/plugins/observability/common/index.ts @@ -25,6 +25,7 @@ export { apmOperationsTab, apmLabsButton, enableInfrastructureHostsView, + enableAwsLambdaMetrics, } from './ui_settings_keys'; export { diff --git a/x-pack/plugins/observability/common/ui_settings_keys.ts b/x-pack/plugins/observability/common/ui_settings_keys.ts index d413cd5d79d13..8167c9a2c5ef5 100644 --- a/x-pack/plugins/observability/common/ui_settings_keys.ts +++ b/x-pack/plugins/observability/common/ui_settings_keys.ts @@ -20,3 +20,4 @@ export const apmTraceExplorerTab = 'observability:apmTraceExplorerTab'; export const apmOperationsTab = 'observability:apmOperationsTab'; export const apmLabsButton = 'observability:apmLabsButton'; export const enableInfrastructureHostsView = 'observability:enableInfrastructureHostsView'; +export const enableAwsLambdaMetrics = 'observability:enableAwsLambdaMetrics'; diff --git a/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx index 15de861284f45..ebdd07ae52995 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/render_cell_value/render_cell_value.tsx @@ -16,6 +16,7 @@ import { TIMESTAMP, } from '@kbn/rule-data-utils'; import type { CellValueElementProps, TimelineNonEcsData } from '@kbn/timelines-plugin/common'; +import { isEmpty } from 'lodash'; import { AlertStatusIndicator } from '../../../../components/shared/alert_status_indicator'; import { TimestampTooltip } from '../../../../components/shared/timestamp_tooltip'; import { asDuration } from '../../../../../common/utils/formatters'; @@ -38,6 +39,20 @@ export const getMappedNonEcsValue = ({ return undefined; }; +const getRenderValue = (mappedNonEcsValue: any) => { + // can be updated when working on https://github.com/elastic/kibana/issues/140819 + const value = Array.isArray(mappedNonEcsValue) ? mappedNonEcsValue.join() : mappedNonEcsValue; + + if (!isEmpty(value)) { + if (typeof value === 'object') { + return JSON.stringify(value); + } + return value; + } + + return '—'; +}; + /** * This implementation of `EuiDataGrid`'s `renderCellValue` * accepts `EuiDataGridCellValueElementProps`, plus `data` @@ -53,10 +68,12 @@ export const getRenderCellValue = ({ }) => { return ({ columnId, data }: CellValueElementProps) => { if (!data) return null; - const value = getMappedNonEcsValue({ + const mappedNonEcsValue = getMappedNonEcsValue({ data, fieldName: columnId, - })?.reduce((x) => x[0]); + }); + + const value = getRenderValue(mappedNonEcsValue); switch (columnId) { case ALERT_STATUS: diff --git a/x-pack/plugins/observability/server/assets/constants.ts b/x-pack/plugins/observability/server/assets/constants.ts index 8afa22d5f695e..4c0cc0e2e6f83 100644 --- a/x-pack/plugins/observability/server/assets/constants.ts +++ b/x-pack/plugins/observability/server/assets/constants.ts @@ -5,11 +5,15 @@ * 2.0. */ -export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = 'observability-slo-mappings'; -export const SLO_COMPONENT_TEMPLATE_SETTINGS_NAME = 'observability-slo-settings'; +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_INGEST_PIPELINE_NAME = 'observability-slo-monthly-index'; export const SLO_RESOURCES_VERSION = 1; +export const getSLOIngestPipelineName = (spaceId: string) => + `${SLO_INDEX_TEMPLATE_NAME}.monthly-${spaceId}`; + export const getSLODestinationIndexName = (spaceId: string) => `${SLO_INDEX_TEMPLATE_NAME}-v${SLO_RESOURCES_VERSION}-${spaceId}`; + +export const getSLOTransformId = (sloId: string) => `slo-${sloId}`; diff --git a/x-pack/plugins/observability/server/errors/errors.ts b/x-pack/plugins/observability/server/errors/errors.ts new file mode 100644 index 0000000000000..2e00a8cc22bfe --- /dev/null +++ b/x-pack/plugins/observability/server/errors/errors.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. + */ + +/* eslint-disable max-classes-per-file */ + +export class ObservabilityError extends Error { + constructor(message?: string) { + super(message); + this.name = this.constructor.name; + } +} + +export class SLONotFound extends ObservabilityError {} diff --git a/x-pack/plugins/observability/server/errors/handler.ts b/x-pack/plugins/observability/server/errors/handler.ts new file mode 100644 index 0000000000000..9ce2dd8b37965 --- /dev/null +++ b/x-pack/plugins/observability/server/errors/handler.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ObservabilityError, SLONotFound } from './errors'; + +export function getHTTPResponseCode(error: ObservabilityError): number { + if (error instanceof SLONotFound) { + return 404; + } + + return 400; +} diff --git a/x-pack/plugins/observability/server/errors/index.ts b/x-pack/plugins/observability/server/errors/index.ts new file mode 100644 index 0000000000000..e466d5b8ae4a1 --- /dev/null +++ b/x-pack/plugins/observability/server/errors/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './errors'; +export * from './handler'; diff --git a/x-pack/plugins/observability/server/routes/register_routes.ts b/x-pack/plugins/observability/server/routes/register_routes.ts index 654c50042148c..e0e9e94f5cb21 100644 --- a/x-pack/plugins/observability/server/routes/register_routes.ts +++ b/x-pack/plugins/observability/server/routes/register_routes.ts @@ -17,6 +17,7 @@ import { RuleDataPluginService } from '@kbn/rule-registry-plugin/server'; import { SpacesServiceStart } from '@kbn/spaces-plugin/server'; import { ObservabilityRequestHandlerContext } from '../types'; import { AbstractObservabilityServerRouteRepository } from './types'; +import { getHTTPResponseCode, ObservabilityError } from '../errors'; export function registerRoutes({ repository, @@ -69,8 +70,30 @@ export function registerRoutes({ spacesService, })) as any; + if (data === undefined) { + return response.noContent(); + } + return response.ok({ body: data }); } catch (error) { + if (error instanceof ObservabilityError) { + logger.error(error.message); + return response.customError({ + statusCode: getHTTPResponseCode(error), + body: { + message: error.message, + }, + }); + } + + if (Boom.isBoom(error)) { + logger.error(error.output.payload.message); + return response.customError({ + statusCode: error.output.statusCode, + body: { message: error.output.payload.message }, + }); + } + logger.error(error); const opts = { statusCode: 500, @@ -79,16 +102,12 @@ export function registerRoutes({ }, }; - if (Boom.isBoom(error)) { - opts.statusCode = error.output.statusCode; - } - if (error instanceof errors.RequestAbortedError) { opts.statusCode = 499; opts.body.message = 'Client closed request'; } - return response.custom(opts); + return response.customError(opts); } } ); diff --git a/x-pack/plugins/observability/server/routes/slo/route.ts b/x-pack/plugins/observability/server/routes/slo/route.ts index 77b87222a60a8..7dfdbc0f29f3c 100644 --- a/x-pack/plugins/observability/server/routes/slo/route.ts +++ b/x-pack/plugins/observability/server/routes/slo/route.ts @@ -7,8 +7,9 @@ import { CreateSLO, + DeleteSLO, DefaultResourceInstaller, - DefaultTransformInstaller, + DefaultTransformManager, KibanaSavedObjectsSLORepository, } from '../../services/slo'; import { @@ -17,7 +18,7 @@ import { TransformGenerator, } from '../../services/slo/transform_generators'; import { SLITypes } from '../../types/models'; -import { createSLOParamsSchema } from '../../types/schema'; +import { createSLOParamsSchema, deleteSLOParamsSchema } from '../../types/schema'; import { createObservabilityServerRoute } from '../create_observability_server_route'; const transformGenerators: Record = { @@ -36,10 +37,15 @@ const createSLORoute = createObservabilityServerRoute({ const soClient = (await context.core).savedObjects.client; const spaceId = spacesService.getSpaceId(request); - const resourceInstaller = new DefaultResourceInstaller(esClient, logger); + const resourceInstaller = new DefaultResourceInstaller(esClient, logger, spaceId); const repository = new KibanaSavedObjectsSLORepository(soClient); - const transformInstaller = new DefaultTransformInstaller(transformGenerators, esClient, logger); - const createSLO = new CreateSLO(resourceInstaller, repository, transformInstaller, spaceId); + const transformManager = new DefaultTransformManager( + transformGenerators, + esClient, + logger, + spaceId + ); + const createSLO = new CreateSLO(resourceInstaller, repository, transformManager); const response = await createSLO.execute(params.body); @@ -47,4 +53,29 @@ const createSLORoute = createObservabilityServerRoute({ }, }); -export const slosRouteRepository = createSLORoute; +const deleteSLORoute = createObservabilityServerRoute({ + endpoint: 'DELETE /api/observability/slos/{id}', + options: { + tags: [], + }, + params: deleteSLOParamsSchema, + handler: async ({ context, request, params, logger, spacesService }) => { + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const soClient = (await context.core).savedObjects.client; + const spaceId = spacesService.getSpaceId(request); + + const repository = new KibanaSavedObjectsSLORepository(soClient); + const transformManager = new DefaultTransformManager( + transformGenerators, + esClient, + logger, + spaceId + ); + + const deleteSLO = new DeleteSLO(repository, transformManager, esClient); + + await deleteSLO.execute(params.path.id); + }, +}); + +export const slosRouteRepository = { ...createSLORoute, ...deleteSLORoute }; diff --git a/x-pack/plugins/observability/server/saved_objects/slo.ts b/x-pack/plugins/observability/server/saved_objects/slo.ts index 13b418e5442c0..59a00cb30a558 100644 --- a/x-pack/plugins/observability/server/saved_objects/slo.ts +++ b/x-pack/plugins/observability/server/saved_objects/slo.ts @@ -39,11 +39,6 @@ export const slo: SavedObjectsType = { target: { type: 'float' }, }, }, - settings: { - properties: { - destination_index: { type: 'text' }, - }, - }, created_at: { type: 'date' }, updated_at: { type: 'date' }, }, diff --git a/x-pack/plugins/observability/server/services/slo/create_slo.test.ts b/x-pack/plugins/observability/server/services/slo/create_slo.test.ts index 69be1c1fa865e..b02afd06571c0 100644 --- a/x-pack/plugins/observability/server/services/slo/create_slo.test.ts +++ b/x-pack/plugins/observability/server/services/slo/create_slo.test.ts @@ -10,57 +10,60 @@ import { createAPMTransactionErrorRateIndicator, createSLOParams } from './fixtu import { createResourceInstallerMock, createSLORepositoryMock, - createTransformInstallerMock, + createTransformManagerMock, } from './mocks'; import { ResourceInstaller } from './resource_installer'; import { SLORepository } from './slo_repository'; -import { TransformInstaller } from './transform_installer'; +import { TransformManager } from './transform_manager'; -const SPACE_ID = 'some-space-id'; - -describe('createSLO', () => { +describe('CreateSLO', () => { let mockResourceInstaller: jest.Mocked; let mockRepository: jest.Mocked; - let mockTransformInstaller: jest.Mocked; + let mockTransformManager: jest.Mocked; let createSLO: CreateSLO; beforeEach(() => { mockResourceInstaller = createResourceInstallerMock(); mockRepository = createSLORepositoryMock(); - mockTransformInstaller = createTransformInstallerMock(); - createSLO = new CreateSLO( - mockResourceInstaller, - mockRepository, - mockTransformInstaller, - SPACE_ID - ); + mockTransformManager = createTransformManagerMock(); + createSLO = new CreateSLO(mockResourceInstaller, mockRepository, mockTransformManager); }); describe('happy path', () => { it('calls the expected services', async () => { const sloParams = createSLOParams(createAPMTransactionErrorRateIndicator()); + mockTransformManager.install.mockResolvedValue('slo-transform-id'); + const response = await createSLO.execute(sloParams); - expect(mockResourceInstaller.ensureCommonResourcesInstalled).toHaveBeenCalledWith(SPACE_ID); + expect(mockResourceInstaller.ensureCommonResourcesInstalled).toHaveBeenCalled(); expect(mockRepository.save).toHaveBeenCalledWith( expect.objectContaining({ ...sloParams, id: expect.any(String) }) ); - expect(mockTransformInstaller.installAndStartTransform).toHaveBeenCalledWith( - expect.objectContaining({ ...sloParams, id: expect.any(String) }), - SPACE_ID + expect(mockTransformManager.install).toHaveBeenCalledWith( + expect.objectContaining({ ...sloParams, id: expect.any(String) }) ); + expect(mockTransformManager.start).toHaveBeenCalledWith('slo-transform-id'); expect(response).toEqual(expect.objectContaining({ id: expect.any(String) })); }); }); describe('unhappy path', () => { - it('deletes the SLO saved objects when transform installation fails', async () => { - mockTransformInstaller.installAndStartTransform.mockRejectedValue( - new Error('Transform Error') - ); + it('deletes the SLO when transform installation fails', async () => { + mockTransformManager.install.mockRejectedValue(new Error('Transform install error')); + const sloParams = createSLOParams(createAPMTransactionErrorRateIndicator()); + + await expect(createSLO.execute(sloParams)).rejects.toThrowError('Transform install error'); + expect(mockRepository.deleteById).toBeCalled(); + }); + + it('removes the transform and deletes the SLO when transform start fails', async () => { + mockTransformManager.install.mockResolvedValue('slo-transform-id'); + mockTransformManager.start.mockRejectedValue(new Error('Transform start error')); const sloParams = createSLOParams(createAPMTransactionErrorRateIndicator()); - await expect(createSLO.execute(sloParams)).rejects.toThrowError('Transform Error'); + await expect(createSLO.execute(sloParams)).rejects.toThrowError('Transform start error'); + expect(mockTransformManager.uninstall).toBeCalledWith('slo-transform-id'); expect(mockRepository.deleteById).toBeCalled(); }); }); diff --git a/x-pack/plugins/observability/server/services/slo/create_slo.ts b/x-pack/plugins/observability/server/services/slo/create_slo.ts index 230955c621760..d04e7013a38f9 100644 --- a/x-pack/plugins/observability/server/services/slo/create_slo.ts +++ b/x-pack/plugins/observability/server/services/slo/create_slo.ts @@ -10,31 +10,41 @@ import uuid from 'uuid'; import { SLO } from '../../types/models'; import { ResourceInstaller } from './resource_installer'; import { SLORepository } from './slo_repository'; -import { TransformInstaller } from './transform_installer'; - +import { TransformManager } from './transform_manager'; import { CreateSLOParams, CreateSLOResponse } from '../../types/schema'; export class CreateSLO { constructor( private resourceInstaller: ResourceInstaller, private repository: SLORepository, - private transformInstaller: TransformInstaller, - private spaceId: string + private transformManager: TransformManager ) {} public async execute(sloParams: CreateSLOParams): Promise { const slo = this.toSLO(sloParams); - await this.resourceInstaller.ensureCommonResourcesInstalled(this.spaceId); + await this.resourceInstaller.ensureCommonResourcesInstalled(); await this.repository.save(slo); + let sloTransformId; try { - await this.transformInstaller.installAndStartTransform(slo, this.spaceId); + sloTransformId = await this.transformManager.install(slo); } catch (err) { await this.repository.deleteById(slo.id); throw err; } + try { + await this.transformManager.start(sloTransformId); + } catch (err) { + await Promise.all([ + this.transformManager.uninstall(sloTransformId), + this.repository.deleteById(slo.id), + ]); + + throw err; + } + return this.toResponse(slo); } @@ -42,9 +52,6 @@ export class CreateSLO { return { ...sloParams, id: uuid.v1(), - settings: { - destination_index: sloParams.settings?.destination_index, - }, }; } diff --git a/x-pack/plugins/observability/server/services/slo/delete_slo.test.ts b/x-pack/plugins/observability/server/services/slo/delete_slo.test.ts new file mode 100644 index 0000000000000..b1a68b9c04aee --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/delete_slo.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; +import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { getSLOTransformId, SLO_INDEX_TEMPLATE_NAME } from '../../assets/constants'; +import { DeleteSLO } from './delete_slo'; +import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; +import { createSLORepositoryMock, createTransformManagerMock } from './mocks'; +import { SLORepository } from './slo_repository'; +import { TransformManager } from './transform_manager'; + +describe('DeleteSLO', () => { + let mockRepository: jest.Mocked; + let mockTransformManager: jest.Mocked; + let mockEsClient: jest.Mocked; + let deleteSLO: DeleteSLO; + + beforeEach(() => { + mockRepository = createSLORepositoryMock(); + mockTransformManager = createTransformManagerMock(); + mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + deleteSLO = new DeleteSLO(mockRepository, mockTransformManager, mockEsClient); + }); + + describe('happy path', () => { + it('removes the transform, the roll up data and the SLO from the repository', async () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + + await deleteSLO.execute(slo.id); + + expect(mockTransformManager.stop).toHaveBeenCalledWith(getSLOTransformId(slo.id)); + expect(mockTransformManager.uninstall).toHaveBeenCalledWith(getSLOTransformId(slo.id)); + expect(mockEsClient.deleteByQuery).toHaveBeenCalledWith( + expect.objectContaining({ + index: `${SLO_INDEX_TEMPLATE_NAME}*`, + query: { + match: { + 'slo.id': slo.id, + }, + }, + }) + ); + expect(mockRepository.deleteById).toHaveBeenCalledWith(slo.id); + }); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/delete_slo.ts b/x-pack/plugins/observability/server/services/slo/delete_slo.ts new file mode 100644 index 0000000000000..59e5df8a5975a --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/delete_slo.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; +import { getSLOTransformId, SLO_INDEX_TEMPLATE_NAME } from '../../assets/constants'; + +import { SLORepository } from './slo_repository'; +import { TransformManager } from './transform_manager'; + +export class DeleteSLO { + constructor( + private repository: SLORepository, + private transformManager: TransformManager, + private esClient: ElasticsearchClient + ) {} + + public async execute(sloId: string): Promise { + const sloTransformId = getSLOTransformId(sloId); + await this.transformManager.stop(sloTransformId); + await this.transformManager.uninstall(sloTransformId); + + await this.deleteRollupData(sloId); + await this.repository.deleteById(sloId); + } + + private async deleteRollupData(sloId: string): Promise { + await this.esClient.deleteByQuery({ + index: `${SLO_INDEX_TEMPLATE_NAME}*`, + wait_for_completion: false, + query: { + match: { + 'slo.id': sloId, + }, + }, + }); + } +} diff --git a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts index 536c9f01c31c1..41ea0ec67991d 100644 --- a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts +++ b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts @@ -30,9 +30,6 @@ export const createSLOParams = (indicator: SLI): CreateSLOParams => ({ export const createSLO = (indicator: SLI): SLO => ({ ...commonSLO, id: uuid.v1(), - settings: { - destination_index: 'some-index', - }, indicator, }); diff --git a/x-pack/plugins/observability/server/services/slo/index.ts b/x-pack/plugins/observability/server/services/slo/index.ts index be64e0b0c0f75..895a7f4497ad5 100644 --- a/x-pack/plugins/observability/server/services/slo/index.ts +++ b/x-pack/plugins/observability/server/services/slo/index.ts @@ -7,5 +7,6 @@ export * from './resource_installer'; export * from './slo_repository'; -export * from './transform_installer'; +export * from './transform_manager'; export * from './create_slo'; +export * from './delete_slo'; diff --git a/x-pack/plugins/observability/server/services/slo/mocks/index.ts b/x-pack/plugins/observability/server/services/slo/mocks/index.ts index 0712fd1c9f8fb..3a9a918fc6480 100644 --- a/x-pack/plugins/observability/server/services/slo/mocks/index.ts +++ b/x-pack/plugins/observability/server/services/slo/mocks/index.ts @@ -7,7 +7,7 @@ import { ResourceInstaller } from '../resource_installer'; import { SLORepository } from '../slo_repository'; -import { TransformInstaller } from '../transform_installer'; +import { TransformManager } from '../transform_manager'; const createResourceInstallerMock = (): jest.Mocked => { return { @@ -15,9 +15,12 @@ const createResourceInstallerMock = (): jest.Mocked => { }; }; -const createTransformInstallerMock = (): jest.Mocked => { +const createTransformManagerMock = (): jest.Mocked => { return { - installAndStartTransform: jest.fn(), + install: jest.fn(), + uninstall: jest.fn(), + start: jest.fn(), + stop: jest.fn(), }; }; @@ -29,4 +32,4 @@ const createSLORepositoryMock = (): jest.Mocked => { }; }; -export { createResourceInstallerMock, createTransformInstallerMock, createSLORepositoryMock }; +export { createResourceInstallerMock, createTransformManagerMock, createSLORepositoryMock }; diff --git a/x-pack/plugins/observability/server/services/slo/resource_installer.test.ts b/x-pack/plugins/observability/server/services/slo/resource_installer.test.ts index 69159d184c0f7..f8746f38cd246 100644 --- a/x-pack/plugins/observability/server/services/slo/resource_installer.test.ts +++ b/x-pack/plugins/observability/server/services/slo/resource_installer.test.ts @@ -9,20 +9,25 @@ import { IngestGetPipelineResponse } from '@elastic/elasticsearch/lib/api/typesW import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { loggerMock } from '@kbn/logging-mocks'; import { + getSLOIngestPipelineName, SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, SLO_INDEX_TEMPLATE_NAME, - SLO_INGEST_PIPELINE_NAME, SLO_RESOURCES_VERSION, } from '../../assets/constants'; import { DefaultResourceInstaller } from './resource_installer'; +const SPACE_ID = 'space-id'; describe('resourceInstaller', () => { describe("when the common resources don't exist", () => { it('installs the common resources', async () => { const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient(); mockClusterClient.indices.existsIndexTemplate.mockResponseOnce(false); - const installer = new DefaultResourceInstaller(mockClusterClient, loggerMock.create()); + const installer = new DefaultResourceInstaller( + mockClusterClient, + loggerMock.create(), + SPACE_ID + ); await installer.ensureCommonResourcesInstalled(); @@ -39,7 +44,7 @@ describe('resourceInstaller', () => { expect.objectContaining({ name: SLO_INDEX_TEMPLATE_NAME }) ); expect(mockClusterClient.ingest.putPipeline).toHaveBeenCalledWith( - expect.objectContaining({ id: SLO_INGEST_PIPELINE_NAME }) + expect.objectContaining({ id: getSLOIngestPipelineName(SPACE_ID) }) ); }); }); @@ -49,9 +54,14 @@ describe('resourceInstaller', () => { const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient(); mockClusterClient.indices.existsIndexTemplate.mockResponseOnce(true); mockClusterClient.ingest.getPipeline.mockResponseOnce({ - [SLO_INGEST_PIPELINE_NAME]: { _meta: { version: SLO_RESOURCES_VERSION } }, + // @ts-ignore _meta not typed properly + [getSLOIngestPipelineName(SPACE_ID)]: { _meta: { version: SLO_RESOURCES_VERSION } }, } as IngestGetPipelineResponse); - const installer = new DefaultResourceInstaller(mockClusterClient, loggerMock.create()); + const installer = new DefaultResourceInstaller( + mockClusterClient, + loggerMock.create(), + SPACE_ID + ); await installer.ensureCommonResourcesInstalled(); diff --git a/x-pack/plugins/observability/server/services/slo/resource_installer.ts b/x-pack/plugins/observability/server/services/slo/resource_installer.ts index ad38710417fed..8ed8108b3c4b7 100644 --- a/x-pack/plugins/observability/server/services/slo/resource_installer.ts +++ b/x-pack/plugins/observability/server/services/slo/resource_installer.ts @@ -13,10 +13,10 @@ import type { import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { + getSLOIngestPipelineName, SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, SLO_INDEX_TEMPLATE_NAME, - SLO_INGEST_PIPELINE_NAME, SLO_RESOURCES_VERSION, } from '../../assets/constants'; import { getSLOMappingsTemplate } from '../../assets/component_templates/slo_mappings_template'; @@ -25,13 +25,17 @@ import { getSLOIndexTemplate } from '../../assets/index_templates/slo_index_temp import { getSLOPipelineTemplate } from '../../assets/ingest_templates/slo_pipeline_template'; export interface ResourceInstaller { - ensureCommonResourcesInstalled(spaceId: string): Promise; + ensureCommonResourcesInstalled(): Promise; } export class DefaultResourceInstaller implements ResourceInstaller { - constructor(private esClient: ElasticsearchClient, private logger: Logger) {} + constructor( + private esClient: ElasticsearchClient, + private logger: Logger, + private spaceId: string + ) {} - public async ensureCommonResourcesInstalled(spaceId: string = 'default'): Promise { + public async ensureCommonResourcesInstalled(): Promise { const alreadyInstalled = await this.areResourcesAlreadyInstalled(); if (alreadyInstalled) { @@ -60,8 +64,8 @@ export class DefaultResourceInstaller implements ResourceInstaller { await this.createOrUpdateIngestPipelineTemplate( getSLOPipelineTemplate( - SLO_INGEST_PIPELINE_NAME, - this.getPipelinePrefix(SLO_RESOURCES_VERSION, spaceId) + getSLOIngestPipelineName(this.spaceId), + this.getPipelinePrefix(SLO_RESOURCES_VERSION, this.spaceId) ) ); } catch (err) { @@ -83,13 +87,12 @@ export class DefaultResourceInstaller implements ResourceInstaller { let ingestPipelineExists = false; try { - const pipeline = await this.esClient.ingest.getPipeline({ - id: SLO_INGEST_PIPELINE_NAME, - }); + const pipelineName = getSLOIngestPipelineName(this.spaceId); + const pipeline = await this.esClient.ingest.getPipeline({ id: pipelineName }); ingestPipelineExists = // @ts-ignore _meta is not defined on the type - pipeline && pipeline[SLO_INGEST_PIPELINE_NAME]._meta.version === SLO_RESOURCES_VERSION; + pipeline && pipeline[pipelineName]._meta.version === SLO_RESOURCES_VERSION; } catch (err) { return false; } diff --git a/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts b/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts index 89c59bb2be7ce..8c8e38285f1f2 100644 --- a/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts +++ b/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts @@ -6,24 +6,16 @@ */ import { SavedObject } from '@kbn/core-saved-objects-common'; -import { SavedObjectsClientContract } from '@kbn/core/server'; +import { SavedObjectsClientContract, SavedObjectsErrorHelpers } from '@kbn/core/server'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; import { SLO, StoredSLO } from '../../types/models'; import { SO_SLO_TYPE } from '../../saved_objects'; import { KibanaSavedObjectsSLORepository } from './slo_repository'; -import { createSLO } from './fixtures/slo'; - -const anSLO = createSLO({ - type: 'slo.apm.transaction_duration', - params: { - environment: 'irrelevant', - service: 'irrelevant', - transaction_type: 'irrelevant', - transaction_name: 'irrelevant', - 'threshold.us': 200000, - }, -}); +import { createAPMTransactionDurationIndicator, createSLO } from './fixtures/slo'; +import { SLONotFound } from '../../errors'; + +const SOME_SLO = createSLO(createAPMTransactionDurationIndicator()); function aStoredSLO(slo: SLO): SavedObject { return { @@ -45,38 +37,61 @@ describe('KibanaSavedObjectsSLORepository', () => { soClientMock = savedObjectsClientMock.create(); }); + describe('validation', () => { + it('findById throws when an SLO is not found', async () => { + soClientMock.get.mockRejectedValueOnce(SavedObjectsErrorHelpers.createGenericNotFoundError()); + const repository = new KibanaSavedObjectsSLORepository(soClientMock); + + 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.delete.mockRejectedValueOnce( + SavedObjectsErrorHelpers.createGenericNotFoundError() + ); + const repository = new KibanaSavedObjectsSLORepository(soClientMock); + + await expect(repository.deleteById('inexistant-slo-id')).rejects.toThrowError( + new SLONotFound('SLO [inexistant-slo-id] not found') + ); + }); + }); + it('saves the SLO', async () => { - soClientMock.create.mockResolvedValueOnce(aStoredSLO(anSLO)); + soClientMock.create.mockResolvedValueOnce(aStoredSLO(SOME_SLO)); const repository = new KibanaSavedObjectsSLORepository(soClientMock); - const savedSLO = await repository.save(anSLO); + const savedSLO = await repository.save(SOME_SLO); - expect(savedSLO).toEqual(anSLO); + expect(savedSLO).toEqual(SOME_SLO); expect(soClientMock.create).toHaveBeenCalledWith( SO_SLO_TYPE, expect.objectContaining({ - ...anSLO, + ...SOME_SLO, updated_at: expect.anything(), created_at: expect.anything(), - }) + }), + { id: SOME_SLO.id } ); }); it('finds an existing SLO', async () => { const repository = new KibanaSavedObjectsSLORepository(soClientMock); - soClientMock.get.mockResolvedValueOnce(aStoredSLO(anSLO)); + soClientMock.get.mockResolvedValueOnce(aStoredSLO(SOME_SLO)); - const foundSLO = await repository.findById(anSLO.id); + const foundSLO = await repository.findById(SOME_SLO.id); - expect(foundSLO).toEqual(anSLO); - expect(soClientMock.get).toHaveBeenCalledWith(SO_SLO_TYPE, anSLO.id); + expect(foundSLO).toEqual(SOME_SLO); + expect(soClientMock.get).toHaveBeenCalledWith(SO_SLO_TYPE, SOME_SLO.id); }); - it('removes an SLO', async () => { + it('deletes an SLO', async () => { const repository = new KibanaSavedObjectsSLORepository(soClientMock); - await repository.deleteById(anSLO.id); + await repository.deleteById(SOME_SLO.id); - expect(soClientMock.delete).toHaveBeenCalledWith(SO_SLO_TYPE, anSLO.id); + expect(soClientMock.delete).toHaveBeenCalledWith(SO_SLO_TYPE, SOME_SLO.id); }); }); diff --git a/x-pack/plugins/observability/server/services/slo/slo_repository.ts b/x-pack/plugins/observability/server/services/slo/slo_repository.ts index cdcfe6b49e760..29e16346fcdb1 100644 --- a/x-pack/plugins/observability/server/services/slo/slo_repository.ts +++ b/x-pack/plugins/observability/server/services/slo/slo_repository.ts @@ -6,9 +6,11 @@ */ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-utils-server'; import { StoredSLO, SLO } from '../../types/models'; import { SO_SLO_TYPE } from '../../saved_objects'; +import { SLONotFound } from '../../errors'; export interface SLORepository { save(slo: SLO): Promise; @@ -21,22 +23,40 @@ export class KibanaSavedObjectsSLORepository implements SLORepository { async save(slo: SLO): Promise { const now = new Date().toISOString(); - const savedSLO = await this.soClient.create(SO_SLO_TYPE, { - ...slo, - created_at: now, - updated_at: now, - }); + const savedSLO = await this.soClient.create( + SO_SLO_TYPE, + { + ...slo, + created_at: now, + updated_at: now, + }, + { id: slo.id } + ); return toSLOModel(savedSLO.attributes); } async findById(id: string): Promise { - const slo = await this.soClient.get(SO_SLO_TYPE, id); - return toSLOModel(slo.attributes); + try { + const slo = await this.soClient.get(SO_SLO_TYPE, id); + return toSLOModel(slo.attributes); + } catch (err) { + if (SavedObjectsErrorHelpers.isNotFoundError(err)) { + throw new SLONotFound(`SLO [${id}] not found`); + } + throw err; + } } async deleteById(id: string): Promise { - await this.soClient.delete(SO_SLO_TYPE, id); + try { + await this.soClient.delete(SO_SLO_TYPE, id); + } catch (err) { + if (SavedObjectsErrorHelpers.isNotFoundError(err)) { + throw new SLONotFound(`SLO [${id}] not found`); + } + throw err; + } } } @@ -49,6 +69,5 @@ function toSLOModel(slo: StoredSLO): SLO { time_window: slo.time_window, budgeting_method: slo.budgeting_method, objective: slo.objective, - settings: slo.settings, }; } diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap index ade6f8b90d894..29ce4877b6b34 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap @@ -20,7 +20,8 @@ Object { "version": 1, }, "dest": Object { - "index": "some-index", + "index": "slo-observability.sli-v1-my-namespace", + "pipeline": "slo-observability.sli.monthly-my-namespace", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap index d07a06e0724cf..58ed238fcf0a7 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap @@ -20,7 +20,8 @@ Object { "version": 1, }, "dest": Object { - "index": "some-index", + "index": "slo-observability.sli-v1-my-namespace", + "pipeline": "slo-observability.sli.monthly-my-namespace", }, "frequency": "1m", "pivot": Object { diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts index c00ba8f69d805..9c0a5aafc693f 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts @@ -10,7 +10,11 @@ import { MappingRuntimeFieldType, TransformPutTransformRequest, } from '@elastic/elasticsearch/lib/api/types'; -import { getSLODestinationIndexName, SLO_INGEST_PIPELINE_NAME } from '../../../assets/constants'; +import { + getSLODestinationIndexName, + getSLOIngestPipelineName, + getSLOTransformId, +} from '../../../assets/constants'; import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; import { SLO, @@ -38,7 +42,7 @@ export class ApmTransactionDurationTransformGenerator implements TransformGenera } private buildTransformId(slo: APMTransactionDurationSLO): string { - return `slo-${slo.id}`; + return getSLOTransformId(slo.id); } private buildSource(slo: APMTransactionDurationSLO) { @@ -101,14 +105,10 @@ export class ApmTransactionDurationTransformGenerator implements TransformGenera } private buildDestination(slo: APMTransactionDurationSLO, spaceId: string) { - if (slo.settings.destination_index === undefined) { - return { - pipeline: SLO_INGEST_PIPELINE_NAME, - index: getSLODestinationIndexName(spaceId), - }; - } - - return { index: slo.settings.destination_index }; + return { + pipeline: getSLOIngestPipelineName(spaceId), + index: getSLODestinationIndexName(spaceId), + }; } private buildGroupBy() { diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts index e418afbead7da..6fa806e72e197 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts @@ -12,7 +12,11 @@ import { } from '@elastic/elasticsearch/lib/api/types'; import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; import { TransformGenerator } from '.'; -import { getSLODestinationIndexName, SLO_INGEST_PIPELINE_NAME } from '../../../assets/constants'; +import { + getSLODestinationIndexName, + getSLOIngestPipelineName, + getSLOTransformId, +} from '../../../assets/constants'; import { apmTransactionErrorRateSLOSchema, APMTransactionErrorRateSLO, @@ -40,7 +44,7 @@ export class ApmTransactionErrorRateTransformGenerator implements TransformGener } private buildTransformId(slo: APMTransactionErrorRateSLO): string { - return `slo-${slo.id}`; + return getSLOTransformId(slo.id); } private buildSource(slo: APMTransactionErrorRateSLO) { @@ -103,14 +107,10 @@ export class ApmTransactionErrorRateTransformGenerator implements TransformGener } private buildDestination(slo: APMTransactionErrorRateSLO, spaceId: string) { - if (slo.settings.destination_index === undefined) { - return { - pipeline: SLO_INGEST_PIPELINE_NAME, - index: getSLODestinationIndexName(spaceId), - }; - } - - return { index: slo.settings.destination_index }; + return { + pipeline: getSLOIngestPipelineName(spaceId), + index: getSLODestinationIndexName(spaceId), + }; } private buildGroupBy() { diff --git a/x-pack/plugins/observability/server/services/slo/transform_installer.test.ts b/x-pack/plugins/observability/server/services/slo/transform_installer.test.ts deleted file mode 100644 index fbe0e7545fc05..0000000000000 --- a/x-pack/plugins/observability/server/services/slo/transform_installer.test.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. - */ -/* eslint-disable max-classes-per-file */ - -import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; -import { ElasticsearchClient } from '@kbn/core/server'; -import { MockedLogger } from '@kbn/logging-mocks'; -import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; - -import { DefaultTransformInstaller } from './transform_installer'; -import { - ApmTransactionErrorRateTransformGenerator, - TransformGenerator, -} from './transform_generators'; -import { SLO, SLITypes } from '../../types/models'; -import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; - -describe('TransformerGenerator', () => { - let esClientMock: jest.Mocked; - let loggerMock: jest.Mocked; - - beforeEach(() => { - esClientMock = elasticsearchServiceMock.createElasticsearchClient(); - loggerMock = loggingSystemMock.createLogger(); - }); - - describe('Unhappy path', () => { - it('throws when no generator exists for the slo indicator type', async () => { - // @ts-ignore defining only a subset of the possible SLI - const generators: Record = { - 'slo.apm.transaction_duration': new DummyTransformGenerator(), - }; - const service = new DefaultTransformInstaller(generators, esClientMock, loggerMock); - - await expect( - service.installAndStartTransform( - createSLO({ - type: 'slo.apm.transaction_error_rate', - params: { - environment: 'irrelevant', - service: 'irrelevant', - transaction_name: 'irrelevant', - transaction_type: 'irrelevant', - }, - }) - ) - ).rejects.toThrowError('Unsupported SLO type: slo.apm.transaction_error_rate'); - }); - - it('throws when transform generator fails', async () => { - // @ts-ignore defining only a subset of the possible SLI - const generators: Record = { - 'slo.apm.transaction_duration': new FailTransformGenerator(), - }; - const service = new DefaultTransformInstaller(generators, esClientMock, loggerMock); - - await expect( - service.installAndStartTransform( - createSLO({ - type: 'slo.apm.transaction_duration', - params: { - environment: 'irrelevant', - service: 'irrelevant', - transaction_name: 'irrelevant', - transaction_type: 'irrelevant', - 'threshold.us': 250000, - }, - }) - ) - ).rejects.toThrowError('Some error'); - }); - }); - - it('installs and starts the transform', async () => { - // @ts-ignore defining only a subset of the possible SLI - const generators: Record = { - 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), - }; - const service = new DefaultTransformInstaller(generators, esClientMock, loggerMock); - - await service.installAndStartTransform(createSLO(createAPMTransactionErrorRateIndicator())); - - expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(1); - expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(1); - }); -}); - -class DummyTransformGenerator implements TransformGenerator { - getTransformParams(slo: SLO): TransformPutTransformRequest { - return {} as TransformPutTransformRequest; - } -} - -class FailTransformGenerator implements TransformGenerator { - getTransformParams(slo: SLO): TransformPutTransformRequest { - throw new Error('Some error'); - } -} diff --git a/x-pack/plugins/observability/server/services/slo/transform_installer.ts b/x-pack/plugins/observability/server/services/slo/transform_installer.ts deleted file mode 100644 index 50fdf1b19ee55..0000000000000 --- a/x-pack/plugins/observability/server/services/slo/transform_installer.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 { errors } from '@elastic/elasticsearch'; -import { ElasticsearchClient, Logger } from '@kbn/core/server'; - -import { SLO, SLITypes } from '../../types/models'; -import { TransformGenerator } from './transform_generators'; - -export interface TransformInstaller { - installAndStartTransform(slo: SLO, spaceId: string): Promise; -} - -export class DefaultTransformInstaller implements TransformInstaller { - constructor( - private generators: Record, - private esClient: ElasticsearchClient, - private logger: Logger - ) {} - - async installAndStartTransform(slo: SLO, spaceId: string = 'default'): Promise { - const generator = this.generators[slo.indicator.type]; - if (!generator) { - this.logger.error(`No transform generator found for ${slo.indicator.type} SLO type`); - throw new Error(`Unsupported SLO type: ${slo.indicator.type}`); - } - - const transformParams = generator.getTransformParams(slo, spaceId); - try { - await this.esClient.transform.putTransform(transformParams); - } catch (err) { - // swallow the error if the transform already exists. - const isAlreadyExistError = - err instanceof errors.ResponseError && - err?.body?.error?.type === 'resource_already_exists_exception'; - if (!isAlreadyExistError) { - this.logger.error(`Cannot create transform for ${slo.indicator.type} SLO type: ${err}`); - throw err; - } - } - - try { - await this.esClient.transform.startTransform( - { transform_id: transformParams.transform_id }, - { ignore: [409] } - ); - } catch (err) { - this.logger.error(`Cannot start transform id ${transformParams.transform_id}: ${err}`); - throw err; - } - } -} diff --git a/x-pack/plugins/observability/server/services/slo/transform_manager.test.ts b/x-pack/plugins/observability/server/services/slo/transform_manager.test.ts new file mode 100644 index 0000000000000..dafa4bff18a52 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_manager.test.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +/* eslint-disable max-classes-per-file */ + +import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { ElasticsearchClient } from '@kbn/core/server'; +import { MockedLogger } from '@kbn/logging-mocks'; +import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; + +import { DefaultTransformManager } from './transform_manager'; +import { + ApmTransactionErrorRateTransformGenerator, + TransformGenerator, +} from './transform_generators'; +import { SLO, SLITypes } from '../../types/models'; +import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; + +const SPACE_ID = 'space-id'; + +describe('TransformManager', () => { + let esClientMock: jest.Mocked; + let loggerMock: jest.Mocked; + + beforeEach(() => { + esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + loggerMock = loggingSystemMock.createLogger(); + }); + + describe('Install', () => { + describe('Unhappy path', () => { + it('throws when no generator exists for the slo indicator type', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_duration': new DummyTransformGenerator(), + }; + const service = new DefaultTransformManager(generators, esClientMock, loggerMock, SPACE_ID); + + await expect( + service.install( + createSLO({ + type: 'slo.apm.transaction_error_rate', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_name: 'irrelevant', + transaction_type: 'irrelevant', + }, + }) + ) + ).rejects.toThrowError('Unsupported SLO type: slo.apm.transaction_error_rate'); + }); + + it('throws when transform generator fails', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_duration': new FailTransformGenerator(), + }; + const transformManager = new DefaultTransformManager( + generators, + esClientMock, + loggerMock, + SPACE_ID + ); + + await expect( + transformManager.install( + createSLO({ + type: 'slo.apm.transaction_duration', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_name: 'irrelevant', + transaction_type: 'irrelevant', + 'threshold.us': 250000, + }, + }) + ) + ).rejects.toThrowError('Some error'); + }); + }); + + it('installs the transform', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), + }; + const transformManager = new DefaultTransformManager( + generators, + esClientMock, + loggerMock, + SPACE_ID + ); + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + + const transformId = await transformManager.install(slo); + + expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(1); + expect(transformId).toBe(`slo-${slo.id}`); + }); + }); + + describe('Start', () => { + it('starts the transform', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), + }; + const transformManager = new DefaultTransformManager( + generators, + esClientMock, + loggerMock, + SPACE_ID + ); + + await transformManager.start('slo-transform-id'); + + expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(1); + }); + }); + + describe('Stop', () => { + it('stops the transform', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), + }; + const transformManager = new DefaultTransformManager( + generators, + esClientMock, + loggerMock, + SPACE_ID + ); + + await transformManager.stop('slo-transform-id'); + + expect(esClientMock.transform.stopTransform).toHaveBeenCalledTimes(1); + }); + }); + + describe('Uninstall', () => { + it('uninstalls the transform', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), + }; + const transformManager = new DefaultTransformManager( + generators, + esClientMock, + loggerMock, + SPACE_ID + ); + + await transformManager.uninstall('slo-transform-id'); + + expect(esClientMock.transform.deleteTransform).toHaveBeenCalledTimes(1); + }); + }); +}); + +class DummyTransformGenerator implements TransformGenerator { + getTransformParams(slo: SLO): TransformPutTransformRequest { + return {} as TransformPutTransformRequest; + } +} + +class FailTransformGenerator implements TransformGenerator { + getTransformParams(slo: SLO): TransformPutTransformRequest { + throw new Error('Some error'); + } +} diff --git a/x-pack/plugins/observability/server/services/slo/transform_manager.ts b/x-pack/plugins/observability/server/services/slo/transform_manager.ts new file mode 100644 index 0000000000000..178d6dacaa433 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_manager.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient, Logger } from '@kbn/core/server'; + +import { SLO, SLITypes } from '../../types/models'; +import { TransformGenerator } from './transform_generators'; + +type TransformId = string; + +export interface TransformManager { + install(slo: SLO): Promise; + start(transformId: TransformId): Promise; + stop(transformId: TransformId): Promise; + uninstall(transformId: TransformId): Promise; +} + +export class DefaultTransformManager implements TransformManager { + constructor( + private generators: Record, + private esClient: ElasticsearchClient, + private logger: Logger, + private spaceId: string + ) {} + + async install(slo: SLO): Promise { + const generator = this.generators[slo.indicator.type]; + if (!generator) { + this.logger.error(`No transform generator found for ${slo.indicator.type} SLO type`); + throw new Error(`Unsupported SLO type: ${slo.indicator.type}`); + } + + const transformParams = generator.getTransformParams(slo, this.spaceId); + try { + await this.esClient.transform.putTransform(transformParams); + } catch (err) { + this.logger.error(`Cannot create transform for ${slo.indicator.type} SLO type: ${err}`); + throw err; + } + + return transformParams.transform_id; + } + + async start(transformId: TransformId): Promise { + try { + await this.esClient.transform.startTransform( + { transform_id: transformId }, + { ignore: [409] } + ); + } catch (err) { + this.logger.error(`Cannot start transform id ${transformId}: ${err}`); + throw err; + } + } + + async stop(transformId: TransformId): Promise { + try { + await this.esClient.transform.stopTransform( + { transform_id: transformId, wait_for_completion: true }, + { ignore: [404] } + ); + } catch (err) { + this.logger.error(`Cannot stop transform id ${transformId}: ${err}`); + throw err; + } + } + + async uninstall(transformId: TransformId): Promise { + try { + await this.esClient.transform.deleteTransform( + { transform_id: transformId, force: true }, + { ignore: [404] } + ); + } catch (err) { + this.logger.error(`Cannot delete transform id ${transformId}: ${err}`); + throw err; + } + } +} diff --git a/x-pack/plugins/observability/server/types/models/slo.ts b/x-pack/plugins/observability/server/types/models/slo.ts index 0cbb60531cc36..7420255b28974 100644 --- a/x-pack/plugins/observability/server/types/models/slo.ts +++ b/x-pack/plugins/observability/server/types/models/slo.ts @@ -25,9 +25,6 @@ const baseSLOSchema = t.type({ objective: t.type({ target: t.number, }), - settings: t.partial({ - destination_index: t.string, - }), }); export const apmTransactionErrorRateSLOSchema = t.intersection([ diff --git a/x-pack/plugins/observability/server/types/schema/slo.ts b/x-pack/plugins/observability/server/types/schema/slo.ts index 888808f129fc0..3d1d3e93bc859 100644 --- a/x-pack/plugins/observability/server/types/schema/slo.ts +++ b/x-pack/plugins/observability/server/types/schema/slo.ts @@ -55,26 +55,17 @@ export const indicatorSchema = t.union([ apmTransactionErrorRateIndicatorSchema, ]); -const sloOptionalSettingsSchema = t.partial({ - settings: t.partial({ - destination_index: t.string, +const createSLOBodySchema = t.type({ + name: t.string, + description: t.string, + indicator: indicatorSchema, + time_window: rollingTimeWindowSchema, + budgeting_method: t.literal('occurrences'), + objective: t.type({ + target: t.number, }), }); -const createSLOBodySchema = t.intersection([ - t.type({ - name: t.string, - description: t.string, - indicator: indicatorSchema, - time_window: rollingTimeWindowSchema, - budgeting_method: t.literal('occurrences'), - objective: t.type({ - target: t.number, - }), - }), - sloOptionalSettingsSchema, -]); - const createSLOResponseSchema = t.type({ id: t.string, }); @@ -85,3 +76,9 @@ export type CreateSLOResponse = t.TypeOf; export const createSLOParamsSchema = t.type({ body: createSLOBodySchema, }); + +export const deleteSLOParamsSchema = t.type({ + path: t.type({ + id: t.string, + }), +}); diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index 6775a7cf51029..21296a9b3e35a 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -23,6 +23,7 @@ import { apmOperationsTab, apmLabsButton, enableInfrastructureHostsView, + enableAwsLambdaMetrics, } from '../common/ui_settings_keys'; const technicalPreviewLabel = i18n.translate( @@ -254,4 +255,26 @@ export const uiSettings: Record = { }), schema: schema.boolean(), }, + [enableAwsLambdaMetrics]: { + category: [observabilityFeatureId], + name: i18n.translate('xpack.observability.enableAwsLambdaMetrics', { + defaultMessage: 'AWS Lambda Metrics', + }), + description: i18n.translate('xpack.observability.enableAwsLambdaMetricsDescription', { + defaultMessage: 'Display Amazon Lambda metrics in the service metrics tab. {feedbackLink}', + values: { + feedbackLink: + '' + + i18n.translate('xpack.observability.awsLambdaDescription', { + defaultMessage: 'Send feedback', + }) + + '', + }, + }), + schema: schema.boolean(), + value: true, + requiresPageReload: true, + type: 'boolean', + showInLabs: true, + }, }; diff --git a/x-pack/plugins/osquery/common/constants.ts b/x-pack/plugins/osquery/common/constants.ts index 4d6be1f3f2ae8..1307d719a5835 100644 --- a/x-pack/plugins/osquery/common/constants.ts +++ b/x-pack/plugins/osquery/common/constants.ts @@ -11,3 +11,5 @@ export const OSQUERY_INTEGRATION_NAME = 'osquery_manager'; export const BASE_PATH = '/app/osquery'; export const ACTIONS_INDEX = `.logs-${OSQUERY_INTEGRATION_NAME}.actions`; export const ACTION_RESPONSES_INDEX = `.logs-${OSQUERY_INTEGRATION_NAME}.action.responses`; + +export const DEFAULT_PLATFORM = 'linux,windows,darwin'; diff --git a/x-pack/plugins/osquery/common/schemas/common/index.ts b/x-pack/plugins/osquery/common/schemas/common/index.ts index 7aa477e1db748..69a2c103f43e7 100644 --- a/x-pack/plugins/osquery/common/schemas/common/index.ts +++ b/x-pack/plugins/osquery/common/schemas/common/index.ts @@ -6,3 +6,4 @@ */ export * from './schemas'; +export * from './utils'; diff --git a/x-pack/plugins/osquery/common/schemas/common/schemas.ts b/x-pack/plugins/osquery/common/schemas/common/schemas.ts index 0e7ae280fca84..5aa1d35437530 100644 --- a/x-pack/plugins/osquery/common/schemas/common/schemas.ts +++ b/x-pack/plugins/osquery/common/schemas/common/schemas.ts @@ -48,6 +48,16 @@ export type Interval = t.TypeOf; export const intervalOrUndefined = t.union([interval, t.undefined]); export type IntervalOrUndefined = t.TypeOf; +export const snapshot = t.boolean; +export type Snapshot = t.TypeOf; +export const snapshotOrUndefined = t.union([snapshot, t.undefined]); +export type SnapshotOrUndefined = t.TypeOf; + +export const removed = t.boolean; +export type Removed = t.TypeOf; +export const removedOrUndefined = t.union([removed, t.undefined]); +export type RemovedOrUndefined = t.TypeOf; + export const savedQueryId = t.string; export type SavedQueryId = t.TypeOf; export const savedQueryIdOrUndefined = t.union([savedQueryId, t.undefined]); diff --git a/x-pack/plugins/osquery/common/schemas/common/utils.ts b/x-pack/plugins/osquery/common/schemas/common/utils.ts index 5e515a756c61f..42326a5798ddd 100644 --- a/x-pack/plugins/osquery/common/schemas/common/utils.ts +++ b/x-pack/plugins/osquery/common/schemas/common/utils.ts @@ -5,18 +5,21 @@ * 2.0. */ -import { isEmpty, map, reduce } from 'lodash'; +import { isEmpty, reduce } from 'lodash'; +import type { DefaultValues } from 'react-hook-form'; import type { ECSMapping } from './schemas'; -export const convertECSMappingToObject = ( - ecsMapping: Array<{ - key: string; - result: { - type: string; - value: string; - }; - }> -): ECSMapping => +export type { ECSMapping }; + +export type ECSMappingArray = Array<{ + key: string; + result: { + type: string; + value: string | string[]; + }; +}>; + +export const convertECSMappingToObject = (ecsMapping: ECSMappingArray): ECSMapping => reduce( ecsMapping, (acc, value) => { @@ -28,23 +31,26 @@ export const convertECSMappingToObject = ( return acc; }, - {} as Record + {} as ECSMapping ); -export type EcsMappingFormValueArray = Array<{ - key: string; - result: { - type: string; - value: string; - }; -}>; -export const convertECSMappingToFormValue = ( - mapping?: Record> -): EcsMappingFormValueArray => - map(mapping, (value, key) => ({ - key, - result: { - type: Object.keys(value)[0], - value: Object.values(value)[0], +export const convertECSMappingToArray = ( + ecsMapping: DefaultValues | undefined +): ECSMappingArray => + reduce( + ecsMapping, + (acc, value, key) => { + if (value) { + acc.push({ + key, + result: { + type: Object.keys(value)[0], + value: Object.values(value as string | string[])[0], + }, + }); + } + + return acc; }, - })); + [] as ECSMappingArray + ); diff --git a/x-pack/plugins/osquery/common/schemas/routes/saved_query/create_saved_query_request_schema.ts b/x-pack/plugins/osquery/common/schemas/routes/saved_query/create_saved_query_request_schema.ts index b58ed0e789cd7..57766307216f0 100644 --- a/x-pack/plugins/osquery/common/schemas/routes/saved_query/create_saved_query_request_schema.ts +++ b/x-pack/plugins/osquery/common/schemas/routes/saved_query/create_saved_query_request_schema.ts @@ -15,6 +15,8 @@ import { query, versionOrUndefined, interval, + snapshotOrUndefined, + removedOrUndefined, ecsMappingOrUndefined, } from '../../common/schemas'; import type { RequiredKeepUndefined } from '../../../types'; @@ -26,6 +28,8 @@ export const createSavedQueryRequestSchema = t.type({ query, version: versionOrUndefined, interval, + snapshot: snapshotOrUndefined, + removed: removedOrUndefined, ecs_mapping: ecsMappingOrUndefined, }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts index 38e6d6f30a661..5204fc8d16c93 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts @@ -28,7 +28,7 @@ describe('ALL - Add Integration', () => { runKbnArchiverScript(ArchiverMethod.UNLOAD, 'saved_query'); }); - it('should add the old integration and be able to upgrade it', () => { + it.skip('should add the old integration and be able to upgrade it', () => { const oldVersion = '0.7.4'; cy.visit(OLD_OSQUERY_MANAGER); @@ -78,7 +78,7 @@ describe('ALL - Add Integration', () => { cy.contains('osquery_manager-'); }); - it('should have integration and packs copied when upgrading integration', () => { + it.skip('should have integration and packs copied when upgrading integration', () => { const packageName = 'osquery_manager'; const oldVersion = '1.2.0'; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts index b53651afa7157..0d77b7f4ff5f1 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts @@ -288,7 +288,7 @@ describe('ALL - Packs', () => { .click(); cy.contains(/^Delete integration$/).click(); closeModalIfVisible(); - cy.contains(/^Deleted integration 'osquery_manager-3'$/); + cy.contains(/^Deleted integration 'osquery_manager-*/); navigateTo('app/osquery/packs'); cy.contains(REMOVING_PACK).click(); cy.contains(`${REMOVING_PACK} details`).should('exist'); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts index e4d76ce9438eb..64fce2e3e0376 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts @@ -9,17 +9,18 @@ import { navigateTo } from '../../tasks/navigation'; import { login } from '../../tasks/login'; import { ROLES } from '../../test'; +import { getSavedQueriesComplexTest } from '../../tasks/saved_queries'; +import { getRandomInt } from '../../tasks/helpers'; describe('ALL - Saved queries', () => { - // const randomNumber = getRandomInt(); - // const SAVED_QUERY_ID = `Saved-Query-Id-${randomNumber}`; - // const SAVED_QUERY_DESCRIPTION = `Test saved query description ${randomNumber}`; + const randomNumber = getRandomInt(); + const SAVED_QUERY_ID = `Saved-Query-Id-${randomNumber}`; + const SAVED_QUERY_DESCRIPTION = `Test saved query description ${randomNumber}`; beforeEach(() => { login(ROLES.soc_manager); navigateTo('/app/osquery'); }); - // TODO usnkip after FF - // getSavedQueriesComplexTest(SAVED_QUERY_ID, SAVED_QUERY_DESCRIPTION); + getSavedQueriesComplexTest(SAVED_QUERY_ID, SAVED_QUERY_DESCRIPTION); }); diff --git a/x-pack/plugins/osquery/public/actions/use_live_query_details.ts b/x-pack/plugins/osquery/public/actions/use_live_query_details.ts index e5d8600be9c86..9c498c3ba82e5 100644 --- a/x-pack/plugins/osquery/public/actions/use_live_query_details.ts +++ b/x-pack/plugins/osquery/public/actions/use_live_query_details.ts @@ -9,7 +9,7 @@ import { useQuery } from '@tanstack/react-query'; import { i18n } from '@kbn/i18n'; import { filter } from 'lodash'; -import type { EcsMappingFormField } from '../packs/queries/ecs_mapping_editor_field'; +import type { ECSMapping } from '../../common/schemas/common'; import { useKibana } from '../common/lib/kibana'; import type { ESTermQuery } from '../../common/typed_json'; import { useErrorToast } from '../common/hooks/use_error_toast'; @@ -27,7 +27,7 @@ export interface PackQueriesQuery { id: string; query: string; agents: string[]; - ecs_mapping?: EcsMappingFormField[]; + ecs_mapping?: ECSMapping; version?: string; platform?: string; saved_query_id?: string; diff --git a/x-pack/plugins/osquery/public/agents/agents_table.tsx b/x-pack/plugins/osquery/public/agents/agents_table.tsx index 2d05780d6545f..9f1d6e59b8168 100644 --- a/x-pack/plugins/osquery/public/agents/agents_table.tsx +++ b/x-pack/plugins/osquery/public/agents/agents_table.tsx @@ -208,4 +208,4 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh AgentsTableComponent.displayName = 'AgentsTable'; -export const AgentsTable = React.memo(AgentsTableComponent); +export const AgentsTable = React.memo(AgentsTableComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/common/helpers.ts b/x-pack/plugins/osquery/public/common/helpers.ts index 6ac79d9ed8870..7697e1d59d5ce 100644 --- a/x-pack/plugins/osquery/public/common/helpers.ts +++ b/x-pack/plugins/osquery/public/common/helpers.ts @@ -42,12 +42,3 @@ export const getInspectResponse = ( response: response != null ? [JSON.stringify(response.rawResponse, null, 2)] : prevResponse?.response, }); - -export const prepareEcsFieldsToValidate = (ecsMapping: Array<{ id: string }>): string[] => - ecsMapping - ?.map((_: unknown, index: number) => [ - `ecs_mapping[${index}].result.value`, - `ecs_mapping[${index}].key`, - ]) - .join(',') - .split(','); diff --git a/x-pack/plugins/osquery/public/form/index.ts b/x-pack/plugins/osquery/public/form/index.ts index 31ea2ac171c88..623477aaa0d16 100644 --- a/x-pack/plugins/osquery/public/form/index.ts +++ b/x-pack/plugins/osquery/public/form/index.ts @@ -9,4 +9,4 @@ export { VersionField } from './version_field'; export { QueryDescriptionField } from './query_description_field'; export { IntervalField } from './interval_field'; export { QueryIdField } from './query_id_field'; -export type { FormField } from './types'; +export { ResultsTypeField } from './results_type_field'; diff --git a/x-pack/plugins/osquery/public/form/interval_field.tsx b/x-pack/plugins/osquery/public/form/interval_field.tsx index d8d1a01804d65..9b5c2001ce2a6 100644 --- a/x-pack/plugins/osquery/public/form/interval_field.tsx +++ b/x-pack/plugins/osquery/public/form/interval_field.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React, { useCallback, useMemo } from 'react'; - +import deepEqual from 'fast-deep-equal'; import { useController } from 'react-hook-form'; import type { EuiFieldNumberProps } from '@elastic/eui'; import { EuiFieldNumber, EuiFormRow } from '@elastic/eui'; @@ -79,4 +79,4 @@ const IntervalFieldComponent = ({ euiFieldProps }: IntervalFieldProps) => { ); }; -export const IntervalField = React.memo(IntervalFieldComponent); +export const IntervalField = React.memo(IntervalFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/form/query_id_field.tsx b/x-pack/plugins/osquery/public/form/query_id_field.tsx index 5910cb9f08dc7..d9f8d362ea3ec 100644 --- a/x-pack/plugins/osquery/public/form/query_id_field.tsx +++ b/x-pack/plugins/osquery/public/form/query_id_field.tsx @@ -8,6 +8,7 @@ import React, { useMemo } from 'react'; import { useController } from 'react-hook-form'; import { EuiFieldText, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import deepEqual from 'fast-deep-equal'; import { createFormIdFieldValidations } from '../packs/queries/validations'; interface QueryIdFieldProps { @@ -49,4 +50,4 @@ const QueryIdFieldComponent = ({ idSet, euiFieldProps }: QueryIdFieldProps) => { ); }; -export const QueryIdField = React.memo(QueryIdFieldComponent); +export const QueryIdField = React.memo(QueryIdFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/form/results_type_field.tsx b/x-pack/plugins/osquery/public/form/results_type_field.tsx new file mode 100644 index 0000000000000..55bbe69397f97 --- /dev/null +++ b/x-pack/plugins/osquery/public/form/results_type_field.tsx @@ -0,0 +1,155 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useEffect, useState } from 'react'; +import { + EuiBetaBadge, + EuiFormRow, + EuiSuperSelect, + EuiFlexGroup, + EuiFlexItem, + EuiText, +} from '@elastic/eui'; +import { useController } from 'react-hook-form'; +import { FormattedMessage } from '@kbn/i18n-react'; +import deepEqual from 'fast-deep-equal'; +import { i18n } from '@kbn/i18n'; + +const SNAPSHOT_OPTION = { + value: 'snapshot', + inputDisplay: ( + + ), +}; + +const DIFFERENTIAL_OPTION = { + value: 'differential', + inputDisplay: ( + + ), +}; + +const DIFFERENTIAL_ADDED_ONLY_OPTION = { + value: 'added_only', + inputDisplay: ( + + ), +}; + +const FIELD_OPTIONS = [SNAPSHOT_OPTION, DIFFERENTIAL_OPTION, DIFFERENTIAL_ADDED_ONLY_OPTION]; + +interface ResultsTypeFieldProps { + euiFieldProps?: Record; +} + +const ResultsTypeFieldComponent: React.FC = ({ euiFieldProps = {} }) => { + const [selectedOption, setSelectedOption] = useState(SNAPSHOT_OPTION.value); + const { + field: { onChange: onSnapshotChange, value: snapshotValue }, + } = useController({ + name: 'snapshot', + defaultValue: true, + }); + + const { + field: { onChange: onRemovedChange, value: removedValue }, + } = useController({ + name: 'removed', + defaultValue: false, + }); + + const handleChange = useCallback( + (newValue) => { + if (newValue === SNAPSHOT_OPTION.value) { + onSnapshotChange(true); + onRemovedChange(false); + } + + if (newValue === DIFFERENTIAL_OPTION.value) { + onSnapshotChange(false); + onRemovedChange(true); + } + + if (newValue === DIFFERENTIAL_ADDED_ONLY_OPTION.value) { + onSnapshotChange(false); + onRemovedChange(false); + } + }, + [onRemovedChange, onSnapshotChange] + ); + + useEffect(() => { + setSelectedOption(() => { + if (snapshotValue) { + return SNAPSHOT_OPTION.value; + } + + if (!snapshotValue && removedValue) { + return DIFFERENTIAL_OPTION.value; + } + + if (!snapshotValue && !removedValue) { + return DIFFERENTIAL_ADDED_ONLY_OPTION.value; + } + + return SNAPSHOT_OPTION.value; + }); + }, [removedValue, snapshotValue]); + + return ( + + + + + + + + + } + labelAppend={ + + + + + + } + fullWidth + > + + + ); +}; + +export const ResultsTypeField = React.memo(ResultsTypeFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/form/types.ts b/x-pack/plugins/osquery/public/form/types.ts index 14f013ac2b012..14b7263c1aa1d 100644 --- a/x-pack/plugins/osquery/public/form/types.ts +++ b/x-pack/plugins/osquery/public/form/types.ts @@ -8,13 +8,6 @@ import type React from 'react'; import type { ReactNode } from 'react'; -export interface FormField { - name: string; - onChange: (data: T) => void; - value: T; - onBlur?: () => void; -} - export interface FormFieldProps { name: string; label: string | Element; diff --git a/x-pack/plugins/osquery/public/form/version_field.tsx b/x-pack/plugins/osquery/public/form/version_field.tsx index f97e26b79a651..ec4a927676e85 100644 --- a/x-pack/plugins/osquery/public/form/version_field.tsx +++ b/x-pack/plugins/osquery/public/form/version_field.tsx @@ -11,6 +11,7 @@ import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiFormRow, EuiComboBox, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import { useController } from 'react-hook-form'; import { FormattedMessage } from '@kbn/i18n-react'; +import deepEqual from 'fast-deep-equal'; interface VersionFieldProps { euiFieldProps?: Record; @@ -85,4 +86,4 @@ const VersionFieldComponent = ({ euiFieldProps = {} }: VersionFieldProps) => { ); }; -export const VersionField = React.memo(VersionFieldComponent); +export const VersionField = React.memo(VersionFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/live_queries/form/index.tsx b/x-pack/plugins/osquery/public/live_queries/form/index.tsx index 5c4c891f99301..a4dc1e97a7c01 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/index.tsx @@ -9,17 +9,12 @@ import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/e import { FormattedMessage } from '@kbn/i18n-react'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useForm as useHookForm, FormProvider } from 'react-hook-form'; -import { isEmpty, map, find, pickBy } from 'lodash'; +import { isEmpty, find, pickBy } from 'lodash'; import type { AddToTimelinePayload } from '../../timelines/get_add_to_timeline'; import { QueryPackSelectable } from './query_pack_selectable'; import type { SavedQuerySOFormData } from '../../saved_queries/form/use_saved_query_form'; -import type { - EcsMappingFormField, - EcsMappingSerialized, -} from '../../packs/queries/ecs_mapping_editor_field'; -import { defaultEcsFormData } from '../../packs/queries/ecs_mapping_editor_field'; -import { convertECSMappingToObject } from '../../../common/schemas/common/utils'; +import type { ECSMapping } from '../../../common/schemas/common/utils'; import { useKibana } from '../../common/lib/kibana'; import { ResultTabs } from '../../routes/saved_queries/edit/tabs'; import { SavedQueryFlyout } from '../../saved_queries'; @@ -37,7 +32,7 @@ export interface LiveQueryFormFields { query?: string; agentSelection: AgentSelection; savedQueryId?: string | null; - ecs_mapping: EcsMappingFormField[]; + ecs_mapping: ECSMapping; packId: string[]; } @@ -45,7 +40,7 @@ interface DefaultLiveQueryFormFields { query?: string; agentSelection?: AgentSelection; savedQueryId?: string | null; - ecs_mapping?: EcsMappingSerialized; + ecs_mapping?: ECSMapping; packId?: string; } @@ -78,11 +73,7 @@ const LiveQueryFormComponent: React.FC = ({ [permissions] ); - const hooksForm = useHookForm({ - defaultValues: { - ecs_mapping: [defaultEcsFormData], - }, - }); + const hooksForm = useHookForm(); const { handleSubmit, watch, @@ -91,7 +82,7 @@ const LiveQueryFormComponent: React.FC = ({ clearErrors, getFieldState, register, - formState: { isSubmitting, errors }, + formState: { isSubmitting }, } = hooksForm; const canRunSingleQuery = useMemo( @@ -131,7 +122,7 @@ const LiveQueryFormComponent: React.FC = ({ }, [register]); const queryStatus = useMemo(() => { - if (isError || queryState.invalid) return 'danger'; + if (isError || queryState.error) return 'danger'; if (isLoading) return 'loading'; if (isSuccess) return 'complete'; @@ -144,28 +135,21 @@ const LiveQueryFormComponent: React.FC = ({ ); const onSubmit = useCallback( - async (values: LiveQueryFormFields) => { + (values: LiveQueryFormFields) => { const serializedData = pickBy( { agentSelection: values.agentSelection, saved_query_id: values.savedQueryId, query: values.query, pack_id: values?.packId?.length ? values?.packId[0] : undefined, - ...(values.ecs_mapping - ? { ecs_mapping: convertECSMappingToObject(values.ecs_mapping) } - : {}), + ecs_mapping: values.ecs_mapping, }, (value) => !isEmpty(value) - ); - if (isEmpty(errors)) { - try { - // @ts-expect-error update types - await mutateAsync(serializedData); - // eslint-disable-next-line no-empty - } catch (e) {} - } + ) as unknown as LiveQueryFormFields; + + mutateAsync(serializedData); }, - [errors, mutateAsync] + [mutateAsync] ); const serializedData: SavedQuerySOFormData = useMemo( @@ -287,18 +271,7 @@ const LiveQueryFormComponent: React.FC = ({ if (defaultValue?.query && canRunSingleQuery) { setValue('query', defaultValue.query); setValue('savedQueryId', defaultValue.savedQueryId); - setValue( - 'ecs_mapping', - !isEmpty(defaultValue.ecs_mapping) - ? map(defaultValue.ecs_mapping, (value, key) => ({ - key, - result: { - type: Object.keys(value)[0], - value: Object.values(value)[0], - }, - })) - : [defaultEcsFormData] - ); + setValue('ecs_mapping', defaultValue.ecs_mapping ?? {}); return; } diff --git a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx index 2938251e177be..c06555dbb8531 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { isEmpty, map } from 'lodash'; +import { isEmpty } from 'lodash'; import type { EuiAccordionProps } from '@elastic/eui'; import { EuiCodeBlock, EuiFormRow, EuiAccordion, EuiSpacer } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; @@ -39,11 +39,11 @@ const LiveQueryQueryFieldComponent: React.FC = ({ disabled, handleSubmitForm, }) => { - const formContext = useFormContext(); + const { watch, resetField } = useFormContext(); const [advancedContentState, setAdvancedContentState] = useState('closed'); const permissions = useKibana().services.application.capabilities.osquery; - const queryType = formContext?.watch('queryType', 'query'); + const queryType = watch('queryType', 'query'); const { field: { onChange, value }, @@ -71,31 +71,18 @@ const LiveQueryQueryFieldComponent: React.FC = ({ const handleSavedQueryChange: SavedQueriesDropdownProps['onChange'] = useCallback( (savedQuery) => { if (savedQuery) { - formContext?.setValue('query', savedQuery.query); - formContext?.setValue('savedQueryId', savedQuery.savedQueryId); - if (!isEmpty(savedQuery.ecs_mapping)) { - formContext?.setValue( - 'ecs_mapping', - map(savedQuery.ecs_mapping, (ecsValue, key) => ({ - key, - result: { - type: Object.keys(ecsValue)[0], - value: Object.values(ecsValue)[0] as string, - }, - })) - ); - } else { - formContext?.resetField('ecs_mapping'); - } + resetField('query', { defaultValue: savedQuery.query }); + resetField('savedQueryId', { defaultValue: savedQuery.savedQueryId }); + resetField('ecs_mapping', { defaultValue: savedQuery.ecs_mapping ?? {} }); if (!isEmpty(savedQuery.ecs_mapping)) { setAdvancedContentState('open'); } } else { - formContext?.setValue('savedQueryId', null); + resetField('savedQueryId'); } }, - [formContext] + [resetField] ); const handleToggle = useCallback((isOpen) => { diff --git a/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx index 38cd6d9cedc3c..39522eba3c3e3 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/pack_queries_status_table.tsx @@ -34,6 +34,7 @@ import type { import { DOCUMENT_FIELD_NAME as RECORDS_FIELD } from '@kbn/lens-plugin/common/constants'; import { FilterStateStore } from '@kbn/es-query'; import styled from 'styled-components'; +import type { ECSMapping } from '../../../common/schemas/common'; import { SECURITY_APP_NAME } from '../../timelines/get_add_to_timeline'; import type { AddToTimelinePayload } from '../../timelines/get_add_to_timeline'; import { PackResultsHeader } from './pack_results_header'; @@ -520,7 +521,7 @@ type PackQueryStatusItem = Partial<{ id: string; query: string; agents: string[]; - ecs_mapping?: unknown; + ecs_mapping?: ECSMapping; version?: string; platform?: string; saved_query_id?: string; diff --git a/x-pack/plugins/osquery/public/live_queries/index.tsx b/x-pack/plugins/osquery/public/live_queries/index.tsx index ba953b4aad6da..986da94c063c1 100644 --- a/x-pack/plugins/osquery/public/live_queries/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/index.tsx @@ -10,8 +10,8 @@ import { EuiCode, EuiLoadingContent, EuiEmptyPrompt } from '@elastic/eui'; import React, { useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import type { ECSMapping } from '../../common/schemas/common'; import type { AddToTimelinePayload } from '../timelines/get_add_to_timeline'; -import type { EcsMappingSerialized } from '../packs/queries/ecs_mapping_editor_field'; import { LiveQueryForm } from './form'; import { useActionResultsPrivileges } from '../action_results/use_action_privileges'; import { OSQUERY_INTEGRATION_NAME } from '../../common'; @@ -25,7 +25,7 @@ interface LiveQueryProps { onSuccess?: () => void; query?: string; savedQueryId?: string; - ecs_mapping?: EcsMappingSerialized; + ecs_mapping?: ECSMapping; agentsField?: boolean; queryField?: boolean; ecsMappingField?: boolean; diff --git a/x-pack/plugins/osquery/public/packs/form/description_field.tsx b/x-pack/plugins/osquery/public/packs/form/description_field.tsx new file mode 100644 index 0000000000000..cdca3749172bd --- /dev/null +++ b/x-pack/plugins/osquery/public/packs/form/description_field.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useMemo } from 'react'; +import { useController } from 'react-hook-form'; +import { EuiFieldText, EuiFormRow } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +interface DescriptionFieldProps { + euiFieldProps?: Record; +} + +const DescriptionFieldComponent: React.FC = ({ euiFieldProps }) => { + const { + field: { onChange, value, name: fieldName }, + fieldState: { error }, + } = useController({ + name: 'description', + defaultValue: '', + }); + + const hasError = useMemo(() => !!error?.message, [error?.message]); + + return ( + + + + ); +}; + +export const DescriptionField = React.memo(DescriptionFieldComponent); diff --git a/x-pack/plugins/osquery/public/packs/form/index.tsx b/x-pack/plugins/osquery/public/packs/form/index.tsx index 51bec779b1f05..594c539c389cf 100644 --- a/x-pack/plugins/osquery/public/packs/form/index.tsx +++ b/x-pack/plugins/osquery/public/packs/form/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { isEmpty, reduce } from 'lodash'; +import { reduce } from 'lodash'; import { EuiFlexGroup, EuiFlexItem, @@ -16,18 +16,10 @@ import { EuiHorizontalRule, } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import deepEqual from 'fast-deep-equal'; +import { FormProvider, useForm as useHookForm } from 'react-hook-form'; -import { - Form, - useForm, - useFormData, - getUseField, - Field, - FIELD_TYPES, - fieldValidators, -} from '../../shared_imports'; import { useRouterNavigate } from '../../common/lib/kibana'; import { PolicyIdComboBoxField } from './policy_id_combobox_field'; import { QueriesField } from './queries_field'; @@ -36,14 +28,12 @@ import { useAgentPolicies } from '../../agent_policies'; import { useCreatePack } from '../use_create_pack'; import { useUpdatePack } from '../use_update_pack'; import { convertPackQueriesToSO, convertSOQueriesToPack } from './utils'; -import { idSchemaValidation } from '../queries/validations'; import type { PackItem } from '../types'; +import { NameField } from './name_field'; +import { DescriptionField } from './description_field'; +import type { PackQueryFormData } from '../queries/use_pack_query_form'; -const GhostFormField = () => <>; - -const FORM_ID = 'scheduledQueryForm'; - -const CommonUseField = getUseField({ component: Field }); +type PackFormData = Omit & { queries: PackQueryFormData[] }; interface PackFormProps { defaultValue?: PackItem; @@ -70,84 +60,53 @@ const PackFormComponent: React.FC = ({ withRedirect: true, }); - const { form } = useForm({ - id: FORM_ID, - schema: { - name: { - type: FIELD_TYPES.TEXT, - label: i18n.translate('xpack.osquery.pack.form.nameFieldLabel', { - defaultMessage: 'Name', - }), - validations: [ - { - validator: idSchemaValidation, - }, - { - validator: fieldValidators.emptyField( - i18n.translate('xpack.osquery.pack.form.nameFieldRequiredErrorMessage', { - defaultMessage: 'Name is a required field', - }) - ), - }, - ], - }, - description: { - type: FIELD_TYPES.TEXT, - label: i18n.translate('xpack.osquery.pack.form.descriptionFieldLabel', { - defaultMessage: 'Description (optional)', - }), - }, - policy_ids: { - defaultValue: [], - type: FIELD_TYPES.COMBO_BOX, - label: i18n.translate('xpack.osquery.pack.form.agentPoliciesFieldLabel', { - defaultMessage: 'Scheduled agent policies (optional)', - }), - helpText: i18n.translate('xpack.osquery.pack.form.agentPoliciesFieldHelpText', { - defaultMessage: 'Queries in this pack are scheduled for agents in the selected policies.', - }), - }, - enabled: { - defaultValue: true, - }, - queries: { - defaultValue: [], - }, - }, - onSubmit: async (formData, isValid) => { - if (isValid) { - try { - if (editMode) { - // @ts-expect-error update types - await updateAsync({ id: defaultValue?.id, ...formData }); - } else { - // @ts-expect-error update types - await createAsync(formData); - } - // eslint-disable-next-line no-empty - } catch (e) {} - } - }, - deserializer: (payload) => ({ - ...payload, - policy_ids: payload.policy_ids ?? [], - queries: convertPackQueriesToSO(payload.queries), - }), - // @ts-expect-error update types - serializer: (payload) => ({ - ...payload, - queries: convertSOQueriesToPack(payload.queries), - }), - defaultValue, + const deserializer = (payload: PackItem) => ({ + ...payload, + policy_ids: payload.policy_ids ?? [], + queries: convertPackQueriesToSO(payload.queries), }); - const { setFieldValue, submit, isSubmitting } = form; + const serializer = (payload: PackFormData) => ({ + ...payload, + queries: convertSOQueriesToPack(payload.queries), + }); - const [{ name: queryName, policy_ids: policyIds }] = useFormData({ - form, - watch: ['name', 'policy_ids'], + const hooksForm = useHookForm({ + defaultValues: defaultValue + ? deserializer(defaultValue) + : { + name: '', + description: '', + policy_ids: [], + enabled: true, + queries: [], + }, }); + const { + handleSubmit, + watch, + formState: { isSubmitting }, + } = hooksForm; + + const onSubmit = useCallback( + async (values: PackFormData) => { + try { + if (editMode && defaultValue?.id) { + await updateAsync({ id: defaultValue?.id, ...serializer(values) }); + } else { + await createAsync(serializer(values)); + } + // eslint-disable-next-line no-empty + } catch (e) {} + }, + [createAsync, defaultValue?.id, editMode, updateAsync] + ); + + const handleSubmitForm = useMemo(() => handleSubmit(onSubmit), [handleSubmit, onSubmit]); + + const { policy_ids: policyIds } = watch(); + const agentCount = useMemo( () => reduce( @@ -162,11 +121,6 @@ const PackFormComponent: React.FC = ({ [policyIds, agentPoliciesById] ); - const handleNameChange = useCallback( - (newName: string) => isEmpty(queryName) && setFieldValue('name', newName), - [queryName, setFieldValue] - ); - const handleSaveClick = useCallback(() => { if (agentCount) { setShowConfirmationModal(true); @@ -174,51 +128,40 @@ const PackFormComponent: React.FC = ({ return; } - submit(); - }, [agentCount, submit]); + handleSubmitForm(); + }, [agentCount, handleSubmitForm]); const handleConfirmConfirmationClick = useCallback(() => { - submit(); + handleSubmitForm(); setShowConfirmationModal(false); - }, [submit]); + }, [handleSubmitForm]); const euiFieldProps = useMemo(() => ({ isDisabled: isReadOnly }), [isReadOnly]); return ( <> -
+ - + - + - + - - - - + +
@@ -272,4 +215,4 @@ const PackFormComponent: React.FC = ({ ); }; -export const PackForm = React.memo(PackFormComponent); +export const PackForm = React.memo(PackFormComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/packs/form/name_field.tsx b/x-pack/plugins/osquery/public/packs/form/name_field.tsx new file mode 100644 index 0000000000000..bb37d0ac5ef7c --- /dev/null +++ b/x-pack/plugins/osquery/public/packs/form/name_field.tsx @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useMemo } from 'react'; +import { useController } from 'react-hook-form'; +import { EuiFieldText, EuiFormRow } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +interface NameFieldProps { + euiFieldProps?: Record; +} + +const NameFieldComponent: React.FC = ({ euiFieldProps }) => { + const { + field: { onChange, value, name: fieldName }, + fieldState: { error }, + } = useController({ + name: 'name', + defaultValue: '', + rules: { + pattern: { + value: /^[a-zA-Z0-9-_]+$/, + message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.invalidIdError', { + defaultMessage: 'Characters must be alphanumeric, _, or -', + }), + }, + required: i18n.translate('xpack.osquery.pack.form.nameFieldRequiredErrorMessage', { + defaultMessage: 'Name is a required field', + }), + }, + }); + + const hasError = useMemo(() => !!error?.message, [error?.message]); + + return ( + + + + ); +}; + +export const NameField = React.memo(NameFieldComponent); diff --git a/x-pack/plugins/osquery/public/packs/form/policy_id_combobox_field.tsx b/x-pack/plugins/osquery/public/packs/form/policy_id_combobox_field.tsx index e91ed3bce4ea0..4f17050f9c537 100644 --- a/x-pack/plugins/osquery/public/packs/form/policy_id_combobox_field.tsx +++ b/x-pack/plugins/osquery/public/packs/form/policy_id_combobox_field.tsx @@ -5,16 +5,16 @@ * 2.0. */ -import { reduce } from 'lodash'; +import { castArray, reduce } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { EuiComboBoxOptionOption } from '@elastic/eui'; -import { EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui'; +import type { EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox, EuiFormRow, EuiFlexGroup, EuiFlexItem, EuiTextColor } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; - -import type { GetAgentPoliciesResponseItem } from '@kbn/fleet-plugin/common'; -import type { FieldHook } from '../../shared_imports'; -import { ComboBoxField } from '../../shared_imports'; +import deepEqual from 'fast-deep-equal'; +import { i18n } from '@kbn/i18n'; +import { useController } from 'react-hook-form'; +import { useAgentPolicies } from '../../agent_policies'; // Custom styling for drop down list items due to: // 1) the max-width and overflow properties is added to prevent long agent policy @@ -30,43 +30,49 @@ const AgentPolicyDescriptionColumn = styled(EuiFlexItem)` overflow: hidden; `; -type ComboBoxFieldProps = Parameters[0]; - -type PolicyIdComboBoxFieldProps = Pick & { - field: FieldHook; - agentPoliciesById: Record; -}; +interface PolicyIdComboBoxFieldProps { + euiFieldProps?: EuiComboBoxProps; +} const PolicyIdComboBoxFieldComponent: React.FC = ({ euiFieldProps, - field, - agentPoliciesById, }) => { - const { value, setValue } = field; + const { data: { agentPoliciesById } = {} } = useAgentPolicies(); + + const { + field: { onChange, value }, + fieldState: { error }, + } = useController<{ policy_ids: string[] }>({ + name: 'policy_ids', + defaultValue: [], + rules: {}, + }); const options = useMemo( () => - Object.entries(agentPoliciesById).map(([agentPolicyId, agentPolicy]) => ({ + Object.entries(agentPoliciesById ?? {}).map(([agentPolicyId, agentPolicy]) => ({ key: agentPolicyId, label: agentPolicy.name, })), [agentPoliciesById] ); - const selectedOptions = useMemo( - () => - value.map((policyId) => ({ + const selectedOptions = useMemo(() => { + if (agentPoliciesById) { + return castArray(value).map((policyId) => ({ key: policyId, label: agentPoliciesById[policyId]?.name ?? policyId, - })), - [agentPoliciesById, value] - ); + })); + } + + return []; + }, [agentPoliciesById, value]); - const onChange = useCallback( + const handleChange = useCallback( (newOptions: EuiComboBoxOptionOption[]) => { - setValue(newOptions.map((option) => option.key || option.label)); + onChange(newOptions.map((option) => option.key || option.label)); }, - [setValue] + [onChange] ); const renderOption = useCallback( @@ -74,12 +80,12 @@ const PolicyIdComboBoxFieldComponent: React.FC = ({ - {(option.key && agentPoliciesById[option.key]?.name) ?? option.label} + {(option.key && agentPoliciesById?.[option.key]?.name) ?? option.label} - {(option.key && agentPoliciesById[option.key].description) ?? ''} + {(option.key && agentPoliciesById?.[option.key].description) ?? ''} @@ -89,7 +95,7 @@ const PolicyIdComboBoxFieldComponent: React.FC = ({ defaultMessage="{count, plural, one {# agent} other {# agents}} enrolled" // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop values={{ - count: (option.key && agentPoliciesById[option.key]?.agents) ?? 0, + count: (option.key && agentPoliciesById?.[option.key]?.agents) ?? 0, }} />
@@ -101,7 +107,12 @@ const PolicyIdComboBoxFieldComponent: React.FC = ({ const helpText = useMemo(() => { if (!value?.length || !value[0].length || !agentPoliciesById) { - return; + return ( + + ); } const agentCount = reduce( @@ -126,28 +137,31 @@ const PolicyIdComboBoxFieldComponent: React.FC = ({ ); }, [agentPoliciesById, value]); - const mergedEuiFieldProps = useMemo( - () => ({ - onCreateOption: null, - noSuggestions: false, - isClearable: true, - selectedOptions, - options, - renderOption, - onChange, - ...euiFieldProps, - }), - [euiFieldProps, onChange, options, renderOption, selectedOptions] - ); + const hasError = useMemo(() => !!error?.message, [error?.message]); return ( - + error={error?.message} + isInvalid={hasError} + fullWidth + > + + ); }; -export const PolicyIdComboBoxField = React.memo(PolicyIdComboBoxFieldComponent); +export const PolicyIdComboBoxField = React.memo(PolicyIdComboBoxFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/packs/form/queries_field.tsx b/x-pack/plugins/osquery/public/packs/form/queries_field.tsx index 62f5c9c7e7e93..03ab8de199269 100644 --- a/x-pack/plugins/osquery/public/packs/form/queries_field.tsx +++ b/x-pack/plugins/osquery/public/packs/form/queries_field.tsx @@ -5,32 +5,46 @@ * 2.0. */ -import { isEmpty, findIndex, forEach, pullAt, pullAllBy, pickBy } from 'lodash'; +import { isEmpty, findIndex, indexOf, pickBy, uniq, map } from 'lodash'; import type { EuiComboBoxProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiSpacer } from '@elastic/eui'; import { produce } from 'immer'; import React, { useCallback, useMemo, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import deepEqual from 'fast-deep-equal'; +import { useController, useFormContext, useWatch, useFieldArray } from 'react-hook-form'; -import type { FieldHook } from '../../shared_imports'; import { PackQueriesTable } from '../pack_queries_table'; import { QueryFlyout } from '../queries/query_flyout'; import { OsqueryPackUploader } from './pack_uploader'; import { getSupportedPlatforms } from '../queries/platforms/helpers'; -import type { PackItem } from '../types'; import type { PackQueryFormData } from '../queries/use_pack_query_form'; interface QueriesFieldProps { - handleNameChange: (name: string) => void; - field: FieldHook; euiFieldProps: EuiComboBoxProps<{}>; } -const QueriesFieldComponent: React.FC = ({ - field, - handleNameChange, - euiFieldProps, -}) => { +const QueriesFieldComponent: React.FC = ({ euiFieldProps }) => { + const { + field: { value: fieldValue }, + } = useController<{ queries: PackQueryFormData[] }, 'queries'>({ + name: 'queries', + defaultValue: [], + rules: {}, + }); + + const { append, remove, update, replace } = useFieldArray({ + name: 'queries', + }); + + const { setValue } = useFormContext(); + const { name: packName } = useWatch(); + + const handleNameChange = useCallback( + (newName: string) => isEmpty(packName) && setValue('name', newName), + [packName, setValue] + ); + const isReadOnly = !!euiFieldProps?.isDisabled; const [showAddQueryFlyout, setShowAddQueryFlyout] = useState(false); const [showEditQueryFlyout, setShowEditQueryFlyout] = useState(-1); @@ -40,61 +54,54 @@ const QueriesFieldComponent: React.FC = ({ const handleHideAddFlyout = useCallback(() => setShowAddQueryFlyout(false), []); const handleHideEditFlyout = useCallback(() => setShowEditQueryFlyout(-1), []); - const { setValue } = field; - const handleDeleteClick = useCallback( (query) => { - const streamIndex = findIndex(field.value, ['id', query.id]); + const streamIndex = findIndex(fieldValue, ['id', query.id]); if (streamIndex > -1) { - setValue( - produce((draft) => { - pullAt(draft, [streamIndex]); - - return draft; - }) - ); + remove(streamIndex); } }, - [field.value, setValue] + [fieldValue, remove] ); const handleEditClick = useCallback( (query) => { - const streamIndex = findIndex(field.value, ['id', query.id]); + const streamIndex = findIndex(fieldValue, ['id', query.id]); setShowEditQueryFlyout(streamIndex); }, - [field.value] + [fieldValue] ); const handleEditQuery = useCallback( (updatedQuery) => new Promise((resolve) => { if (showEditQueryFlyout >= 0) { - setValue( - produce((draft) => { - draft[showEditQueryFlyout].id = updatedQuery.id; - draft[showEditQueryFlyout].interval = updatedQuery.interval; - draft[showEditQueryFlyout].query = updatedQuery.query; + update( + showEditQueryFlyout, + produce({}, (draft: PackQueryFormData) => { + draft.id = updatedQuery.id; + draft.interval = updatedQuery.interval; + draft.query = updatedQuery.query; if (updatedQuery.platform?.length) { - draft[showEditQueryFlyout].platform = updatedQuery.platform; - } else { - delete draft[showEditQueryFlyout].platform; + draft.platform = updatedQuery.platform; } if (updatedQuery.version?.length) { - draft[showEditQueryFlyout].version = updatedQuery.version; - } else { - delete draft[showEditQueryFlyout].version; + draft.version = updatedQuery.version; } if (updatedQuery.ecs_mapping) { - draft[showEditQueryFlyout].ecs_mapping = updatedQuery.ecs_mapping; - } else { - // @ts-expect-error update types - delete draft[showEditQueryFlyout].ecs_mapping; + draft.ecs_mapping = updatedQuery.ecs_mapping; + } + + if (updatedQuery.snapshot === false) { + draft.snapshot = updatedQuery.snapshot; + if (updatedQuery.removed !== undefined) { + draft.removed = updatedQuery.removed; + } } return draft; @@ -105,80 +112,53 @@ const QueriesFieldComponent: React.FC = ({ handleHideEditFlyout(); resolve(); }), - [handleHideEditFlyout, setValue, showEditQueryFlyout] + [handleHideEditFlyout, update, showEditQueryFlyout] ); const handleAddQuery = useCallback( (newQuery) => new Promise((resolve) => { - setValue( - produce((draft) => { - draft.push(newQuery); - - return draft; - }) - ); + append(newQuery); handleHideAddFlyout(); resolve(); }), - [handleHideAddFlyout, setValue] + [handleHideAddFlyout, append] ); const handleDeleteQueries = useCallback(() => { - setValue( - produce((draft) => { - pullAllBy(draft, tableSelectedItems, 'id'); - - return draft; - }) + const idsToRemove = map(tableSelectedItems, (selectedItem) => + indexOf(fieldValue, selectedItem) ); + remove(idsToRemove); setTableSelectedItems([]); - }, [setValue, tableSelectedItems]); + }, [fieldValue, remove, tableSelectedItems]); const handlePackUpload = useCallback( - (parsedContent, packName) => { - setValue( - produce((draft) => { - forEach(parsedContent.queries, (newQuery, newQueryId) => { - draft.push( - // @ts-expect-error update types - pickBy( - { - id: newQueryId, - interval: newQuery.interval ?? parsedContent.interval ?? '3600', - query: newQuery.query, - version: newQuery.version ?? parsedContent.version, - platform: getSupportedPlatforms(newQuery.platform ?? parsedContent.platform), - }, - (value) => !isEmpty(value) - ) - ); - }); - - return draft; - }) + (parsedContent, uploadedPackName) => { + replace( + map(parsedContent.queries, (newQuery, newQueryId) => + pickBy( + { + id: newQueryId, + interval: newQuery.interval ?? parsedContent.interval ?? '3600', + query: newQuery.query, + version: newQuery.version ?? parsedContent.version, + snapshot: newQuery.snapshot ?? parsedContent.snapshot, + removed: newQuery.removed ?? parsedContent.removed, + platform: getSupportedPlatforms(newQuery.platform ?? parsedContent.platform), + }, + (value) => !isEmpty(value) || value === false + ) + ) ); - handleNameChange(packName); + handleNameChange(uploadedPackName); }, - [handleNameChange, setValue] + [handleNameChange, replace] ); - const tableData = useMemo(() => (field.value?.length ? field.value : []), [field.value]); - - const uniqueQueryIds = useMemo( - () => - field.value && field.value.length - ? field.value.reduce((acc, query) => { - if (query?.id) { - acc.push(query.id); - } - - return acc; - }, [] as string[]) - : [], - [field.value] - ); + const tableData = useMemo(() => (fieldValue?.length ? fieldValue : []), [fieldValue]); + const uniqueQueryIds = useMemo(() => uniq(map(fieldValue, 'id')), [fieldValue]); return ( <> @@ -210,7 +190,7 @@ const QueriesFieldComponent: React.FC = ({ )} - {field.value?.length ? ( + {fieldValue?.length ? ( = ({ @@ -242,4 +222,4 @@ const QueriesFieldComponent: React.FC = ({ ); }; -export const QueriesField = React.memo(QueriesFieldComponent); +export const QueriesField = React.memo(QueriesFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/packs/form/utils.ts b/x-pack/plugins/osquery/public/packs/form/utils.ts index 446172c1cd5ce..e04db1ed5b237 100644 --- a/x-pack/plugins/osquery/public/packs/form/utils.ts +++ b/x-pack/plugins/osquery/public/packs/form/utils.ts @@ -6,25 +6,31 @@ */ import { pick, reduce } from 'lodash'; +import type { PackQueryFormData } from '../queries/use_pack_query_form'; -// @ts-expect-error update types -export const convertPackQueriesToSO = (queries) => +export const convertPackQueriesToSO = (queries: Record>) => reduce( queries, (acc, value, key) => { acc.push({ - // @ts-expect-error update types id: key, - ...pick(value, ['query', 'interval', 'platform', 'version', 'ecs_mapping']), + ...pick(value, [ + 'query', + 'interval', + 'snapshot', + 'removed', + 'platform', + 'version', + 'ecs_mapping', + ]), }); return acc; }, - [] + [] as PackQueryFormData[] ); -// @ts-expect-error update types -export const convertSOQueriesToPack = (queries) => +export const convertSOQueriesToPack = (queries: PackQueryFormData[]) => reduce( queries, (acc, { id: queryId, ...query }) => { @@ -32,6 +38,5 @@ export const convertSOQueriesToPack = (queries) => return acc; }, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - {} as Record + {} as Record> ); diff --git a/x-pack/plugins/osquery/public/packs/pack_queries_table.tsx b/x-pack/plugins/osquery/public/packs/pack_queries_table.tsx index 4bf2c96b6a649..60569ebaf184a 100644 --- a/x-pack/plugins/osquery/public/packs/pack_queries_table.tsx +++ b/x-pack/plugins/osquery/public/packs/pack_queries_table.tsx @@ -10,16 +10,15 @@ import { EuiBasicTable, EuiCodeBlock, EuiButtonIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { PlatformIcons } from './queries/platforms'; -import type { PackItem } from './types'; import type { PackQueryFormData } from './queries/use_pack_query_form'; export interface PackQueriesTableProps { - data: PackItem['queries']; + data: PackQueryFormData[]; isReadOnly?: boolean; onDeleteClick?: (item: PackQueryFormData) => void; onEditClick?: (item: PackQueryFormData) => void; - selectedItems?: PackItem['queries']; - setSelectedItems?: (selection: PackItem['queries']) => void; + selectedItems?: PackQueryFormData[]; + setSelectedItems?: (selection: PackQueryFormData[]) => void; } const PackQueriesTableComponent: React.FC = ({ diff --git a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx index f0da49b7c216b..588c681ea5dfb 100644 --- a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx @@ -6,6 +6,7 @@ */ import { + last, castArray, each, isEmpty, @@ -17,6 +18,7 @@ import { reduce, trim, get, + reject, } from 'lodash'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import type { EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; @@ -38,32 +40,21 @@ import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; -import { useController, useFieldArray, useFormContext, useWatch } from 'react-hook-form'; -import type { FormField } from '../../form/types'; +import type { InternalFieldErrors, UseFieldArrayRemove, UseFormReturn } from 'react-hook-form'; +import { useForm, useController, useFieldArray, useFormContext } from 'react-hook-form'; +import type { ECSMappingArray, ECSMapping } from '../../../common/schemas/common/utils'; +import { + convertECSMappingToArray, + convertECSMappingToObject, +} from '../../../common/schemas/common/utils'; import ECSSchema from '../../common/schemas/ecs/v8.4.0.json'; import osquerySchema from '../../common/schemas/osquery/v5.4.0.json'; import { FieldIcon } from '../../common/lib/kibana'; -import type { FormArrayField } from '../../shared_imports'; import { OsqueryIcon } from '../../components/osquery_icon'; import { removeMultilines } from '../../../common/utils/build_query/remove_multilines'; -import { prepareEcsFieldsToValidate } from '../../common/helpers'; - -export interface EcsMappingFormField { - key: string; - result: { - type: string; - value: string; - }; -} -export type EcsMappingSerialized = Record< - string, - { - field?: string; - value?: string; - } ->; +export type ECSMappingFormReturn = UseFormReturn<{ ecsMappingArray: ECSMappingArray }>; const typeMap = { binary: 'binary', @@ -148,8 +139,11 @@ const ECSSchemaOptions = ECSSchema.map((ecs) => ({ type ECSSchemaOption = typeof ECSSchemaOptions[0]; -interface ECSComboboxFieldProps extends FormField { +interface ECSComboboxFieldProps { euiFieldProps: EuiComboBoxProps; + control: ECSMappingFormReturn['control']; + watch: ECSMappingFormReturn['watch']; + index: number; idAria?: string; error?: string; } @@ -157,23 +151,43 @@ interface ECSComboboxFieldProps extends FormField { const ECSComboboxFieldComponent: React.FC = ({ euiFieldProps = {}, idAria, - onChange, - value, - error, + index, + watch, + control, }) => { + const { ecsMappingArray } = watch(); + const ecsCurrentMapping = get(ecsMappingArray, `[${index}].result.value`); + + const ecsFieldValidator = useCallback( + (value: string) => + !value?.length && ecsCurrentMapping?.length + ? i18n.translate('xpack.osquery.pack.queryFlyoutForm.ecsFieldRequiredErrorMessage', { + defaultMessage: 'ECS field is required.', + }) + : undefined, + [ecsCurrentMapping?.length] + ); + + const { field: ECSField, fieldState: ECSFieldState } = useController({ + control, + name: `ecsMappingArray.${index}.key`, + rules: { + validate: ecsFieldValidator, + }, + defaultValue: '', + }); + const [selectedOptions, setSelected] = useState>>( [] ); const describedByIds = useMemo(() => (idAria ? [idAria] : []), [idAria]); - const { ecs_mapping: watchedEcsMapping } = useWatch() as unknown as { - ecs_mapping: EcsMappingFormField[]; - }; + const { ecsMappingArray: watchedEcsMapping } = watch(); const handleChange = useCallback( (newSelectedOptions) => { setSelected(newSelectedOptions); - onChange(newSelectedOptions[0]?.label ?? ''); + ECSField.onChange(newSelectedOptions[0]?.label ?? ''); }, - [onChange] + [ECSField] ); // TODO: Create own component for this. @@ -243,22 +257,22 @@ const ECSComboboxFieldComponent: React.FC = ({ useEffect(() => { // @ts-expect-error update types setSelected(() => { - if (!value?.length) return []; + if (!ECSField.value?.length) return []; - const selectedOption = find(ECSSchemaOptions, ['label', value]); + const selectedOption = find(ECSSchemaOptions, ['label', ECSField.value]); return selectedOption ? [selectedOption] : [ { - label: value, + label: ECSField.value, value: { - value, + value: ECSField.value, }, }, ]; }); - }, [value]); + }, [ECSField.value]); return ( = ({ defaultMessage: 'ECS field', })} helpText={helpText} - error={error} - isInvalid={!!error} + error={ECSFieldState.error?.message} + isInvalid={!!ECSFieldState.error?.message?.length} fullWidth describedByIds={describedByIds} isDisabled={euiFieldProps.isDisabled} @@ -276,6 +290,7 @@ const ECSComboboxFieldComponent: React.FC = ({ prepend={prepend} fullWidth singleSelection={SINGLE_SELECTION} + error={ECSFieldState.error?.message} // @ts-expect-error update types options={availableECSSchemaOptions} selectedOptions={selectedOptions} @@ -290,7 +305,7 @@ const ECSComboboxFieldComponent: React.FC = ({ ); }; -export const ECSComboboxField = React.memo(ECSComboboxFieldComponent); +export const ECSComboboxField = React.memo(ECSComboboxFieldComponent, deepEqual); const OSQUERY_COLUMN_VALUE_TYPE_OPTIONS = [ { @@ -337,8 +352,10 @@ const EMPTY_ARRAY: EuiComboBoxOptionOption[] = []; interface OsqueryColumnFieldProps { euiFieldProps: EuiComboBoxProps; - item: EcsMappingFormField; index: number; + control: ECSMappingFormReturn['control']; + watch: ECSMappingFormReturn['watch']; + trigger: ECSMappingFormReturn['trigger']; idAria?: string; isLastItem: boolean; } @@ -346,59 +363,64 @@ interface OsqueryColumnFieldProps { const OsqueryColumnFieldComponent: React.FC = ({ euiFieldProps, idAria, - item, index, isLastItem, + control, + watch, + trigger, }) => { - const osqueryResultFieldValidator = ( - value: string, - ecsMappingFormData: EcsMappingFormField[] - ): string | undefined => { - const currentMapping = ecsMappingFormData[index]; - - if (!value.length && currentMapping.key.length) { - return i18n.translate( - 'xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldRequiredErrorMessage', - { - defaultMessage: 'Value field is required.', - } - ); - } - - if (!value.length || currentMapping.result.type !== 'field') return; + const { ecsMappingArray } = watch(); - const osqueryColumnExists = find(euiFieldProps.options, [ - 'label', - isArray(value) ? value[0] : value, - ]); + const osqueryResultFieldValidator = useCallback( + (value: string | string[]): string | undefined => { + const currentMapping = ecsMappingArray && ecsMappingArray[index]; - return !osqueryColumnExists - ? i18n.translate( - 'xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldValueMissingErrorMessage', + if (!value?.length && currentMapping?.key?.length) { + return i18n.translate( + 'xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldRequiredErrorMessage', { - defaultMessage: 'The current query does not return a {columnName} field', - values: { - columnName: value, - }, + defaultMessage: 'Value field is required.', } - ) - : undefined; - }; + ); + } - const { setValue } = useFormContext(); - const { ecs_mapping: watchedEcsMapping } = useWatch() as unknown as { - ecs_mapping: EcsMappingFormField[]; - }; + if (!value?.length || currentMapping?.result?.type !== 'field') return; + + const osqueryColumnExists = find(euiFieldProps.options, [ + 'label', + isArray(value) ? value[0] : value, + ]); + + return !osqueryColumnExists + ? i18n.translate( + 'xpack.osquery.pack.queryFlyoutForm.osqueryResultFieldValueMissingErrorMessage', + { + defaultMessage: 'The current query does not return a {columnName} field', + values: { + columnName: isArray(value) ? value[0] : value, + }, + } + ) + : undefined; + }, + [ecsMappingArray, euiFieldProps.options, index] + ); + + const { field: resultTypeField } = useController({ + control, + name: `ecsMappingArray.${index}.result.type`, + defaultValue: OSQUERY_COLUMN_VALUE_TYPE_OPTIONS[0].value, + }); const { field: resultField, fieldState: resultFieldState } = useController({ - name: `ecs_mapping.${index}.result.value`, + control, + name: `ecsMappingArray.${index}.result.value`, rules: { - validate: (data) => osqueryResultFieldValidator(data, watchedEcsMapping), + validate: osqueryResultFieldValidator, }, defaultValue: '', }); - const itemPath = `ecs_mapping.${index}`; - const resultValue = item.result; + const inputRef = useRef(); const [selectedOptions, setSelected] = useState([]); const describedByIds = useMemo(() => (idAria ? [idAria] : []), [idAria]); @@ -438,8 +460,8 @@ const OsqueryColumnFieldComponent: React.FC = ({ ); const isSingleSelection = useMemo(() => { - const ecsData = get(watchedEcsMapping, `${index}`); - if (ecsData?.key?.length && item.result.type === 'value') { + const ecsData = get(ecsMappingArray, `${index}`); + if (ecsData?.key?.length && resultTypeField.value === 'value') { const ecsKeySchemaOption = find(ECSSchemaOptions, ['label', ecsData?.key]); return ecsKeySchemaOption?.value?.normalization !== 'array'; @@ -450,19 +472,16 @@ const OsqueryColumnFieldComponent: React.FC = ({ } return !!ecsData?.key?.length; - }, [index, isLastItem, item.result.type, watchedEcsMapping]); + }, [ecsMappingArray, index, isLastItem, resultTypeField.value]); const onTypeChange = useCallback( (newType) => { - if (newType !== item.result.type) { - setValue(`${itemPath}.result.type`, newType); - setValue( - `${itemPath}.result.value`, - newType === 'value' && isSingleSelection === false ? [] : '' - ); + if (newType !== resultTypeField.value) { + resultTypeField.onChange(newType); + resultField.onChange(newType === 'value' && isSingleSelection === false ? [] : ''); } }, - [isSingleSelection, item.result.type, itemPath, setValue] + [isSingleSelection, resultField, resultTypeField] ); const handleCreateOption = useCallback( @@ -472,19 +491,19 @@ const OsqueryColumnFieldComponent: React.FC = ({ if (!trimmedNewOption.length) return; if (isSingleSelection === false) { - setValue(`${itemPath}.result.value`, [trimmedNewOption]); - if (item.result.value.length) { - setValue(`${itemPath}.result.value`, [...castArray(resultValue.value), trimmedNewOption]); + resultField.onChange([trimmedNewOption]); + if (resultField.value?.length) { + resultField.onChange([...castArray(resultField.value), trimmedNewOption]); } else { - setValue(`${itemPath}.result.value`, [trimmedNewOption]); + resultField.onChange([trimmedNewOption]); } inputRef.current?.blur(); } else { - setValue(`${itemPath}.result.value`, trimmedNewOption); + resultField.onChange(trimmedNewOption); } }, - [isSingleSelection, item.result.value.length, itemPath, resultValue.value, setValue] + [isSingleSelection, resultField] ); const Prepend = useMemo( @@ -492,7 +511,7 @@ const OsqueryColumnFieldComponent: React.FC = ({ = ({ onChange={onTypeChange} /> ), - [euiFieldProps.isDisabled, item.result.type, onTypeChange] + [euiFieldProps.isDisabled, onTypeChange, resultTypeField.value] ); useEffect(() => { - if (isSingleSelection && isArray(resultValue.value)) { - setValue(`${itemPath}.result.value`, resultValue.value.join(' ')); + if (isSingleSelection && isArray(resultField.value)) { + resultField.onChange(resultField.value.join(' ')); } - if (!isSingleSelection && !isArray(resultValue.value)) { - const value = resultValue.value.length ? [resultValue.value] : []; - setValue(`${itemPath}.result.value`, value); + if (!isSingleSelection && !isArray(resultField.value)) { + const value = resultField.value.length ? [resultField.value] : []; + resultField.onChange(value); } - }, [index, isSingleSelection, itemPath, resultValue, resultValue.value, setValue]); + }, [index, isSingleSelection, resultField, resultField.value]); useEffect(() => { // @ts-expect-error hard to type to satisfy TS, but it represents proper types setSelected((_: OsquerySchemaOption[]): OsquerySchemaOption[] | Array<{ label: string }> => { - if (!resultValue.value.length) return []; + if (!resultField.value?.length) return []; // Static array values - if (isArray(resultValue.value)) { - return resultValue.value.map((value) => ({ label: value })) as OsquerySchemaOption[]; + if (isArray(resultField.value)) { + return resultField.value.map((value) => ({ label: value })) as OsquerySchemaOption[]; } - const selectedOption = find(euiFieldProps?.options, ['label', resultValue.value]) as + const selectedOption = find(euiFieldProps?.options, ['label', resultField.value]) as | OsquerySchemaOption | undefined; - return selectedOption ? [selectedOption] : [{ label: resultValue.value }]; + return selectedOption ? [selectedOption] : [{ label: resultField.value }]; }); - }, [euiFieldProps?.options, setSelected, resultValue.value]); + }, [euiFieldProps?.options, setSelected, resultField.value]); + + useEffect(() => { + trigger(`ecsMappingArray.${index}.key`); + }, [resultField.value, trigger, index]); return ( = ({ {Prepend} { @@ -566,7 +586,7 @@ const OsqueryColumnFieldComponent: React.FC = ({ rowHeight={32} isClearable singleSelection={isSingleSelection ? SINGLE_SELECTION : false} - options={(item.result.type === 'field' && euiFieldProps.options) || EMPTY_ARRAY} + options={(resultTypeField.value === 'field' && euiFieldProps.options) || EMPTY_ARRAY} idAria={idAria} helpText={selectedOptions[0]?.value?.description} {...euiFieldProps} @@ -577,7 +597,7 @@ const OsqueryColumnFieldComponent: React.FC = ({ ); }; -export const OsqueryColumnField = React.memo(OsqueryColumnFieldComponent); +export const OsqueryColumnField = React.memo(OsqueryColumnFieldComponent, deepEqual); export interface ECSMappingEditorFieldProps { euiFieldProps?: EuiComboBoxProps<{}>; @@ -586,11 +606,12 @@ export interface ECSMappingEditorFieldProps { interface ECSMappingEditorFormProps { isDisabled?: boolean; osquerySchemaOptions: OsquerySchemaOption[]; - item: EcsMappingFormField; index: number; isLastItem: boolean; - onAppend: (ecs_mapping: EcsMappingFormField[]) => void; - onDelete?: FormArrayField['removeItem']; + control: ECSMappingFormReturn['control']; + watch: ECSMappingFormReturn['watch']; + trigger: ECSMappingFormReturn['trigger']; + onDelete?: UseFieldArrayRemove; } export const defaultEcsFormData = { @@ -604,34 +625,13 @@ export const defaultEcsFormData = { export const ECSMappingEditorForm: React.FC = ({ isDisabled, osquerySchemaOptions, - item, isLastItem, index, onDelete, + control, + watch, + trigger, }) => { - const ecsFieldValidator = (value: string, ecsMapping: EcsMappingFormField[]) => { - const ecsCurrentMapping = ecsMapping[index].result.value; - - return !value.length && ecsCurrentMapping.length - ? i18n.translate('xpack.osquery.pack.queryFlyoutForm.ecsFieldRequiredErrorMessage', { - defaultMessage: 'ECS field is required.', - }) - : undefined; - }; - - const { ecs_mapping: ecsMapping } = useWatch() as unknown as { - ecs_mapping: EcsMappingFormField[]; - }; - const { field: ECSField, fieldState: ECSFieldState } = useController({ - name: `ecs_mapping.${index}.key`, - rules: { - validate: (value: string) => ecsFieldValidator(value, ecsMapping), - }, - defaultValue: '', - }); - - const ecsComboBoxEuiFieldProps = useMemo(() => ({ isDisabled }), [isDisabled]); - const handleDeleteClick = useCallback(() => { if (onDelete) { onDelete(index); @@ -645,12 +645,13 @@ export const ECSMappingEditorForm: React.FC = ({ @@ -664,7 +665,9 @@ export const ECSMappingEditorForm: React.FC = ({ { - const { trigger } = useFormContext(); - const { fields, append, remove } = useFieldArray<{ ecs_mapping: EcsMappingFormField[] }>({ - name: 'ecs_mapping', - }); +export const ECSMappingEditorField = React.memo(({ euiFieldProps }: ECSMappingEditorFieldProps) => { + const { + setError, + clearErrors, + watch: watchRoot, + register: registerRoot, + setValue: setValueRoot, + formState: { errors: errorsRoot }, + } = useFormContext<{ query: string; ecs_mapping: ECSMapping }>(); - const itemsList = useRef>([]); - const [osquerySchemaOptions, setOsquerySchemaOptions] = useState([]); - const { query, ...formData } = useWatch() as unknown as { - query: string; - ecs_mapping: EcsMappingFormField[]; - }; - - useEffect(() => { - // Additional 'suspended' validation of osquery ecs fields. fieldsToValidateOnChange doesn't work because it happens before the osquerySchema gets updated. - const fieldsToValidate = prepareEcsFieldsToValidate(fields); - // it is always at least 2 - empty fields - if (fieldsToValidate.length > 2) { - setTimeout(() => trigger('ecs_mapping'), 0); + useEffect(() => { + registerRoot('ecs_mapping'); + }, [registerRoot]); + + const [query, ecsMapping] = watchRoot(['query', 'ecs_mapping'], { ecs_mapping: {} }); + const { control, trigger, watch, formState, resetField, getFieldState } = useForm<{ + ecsMappingArray: ECSMappingArray; + }>({ + mode: 'all', + shouldUnregister: true, + defaultValues: { + ecsMappingArray: !isEmpty(convertECSMappingToArray(ecsMapping)) + ? [...convertECSMappingToArray(ecsMapping), defaultEcsFormData] + : [defaultEcsFormData], + }, + }); + const { fields, append, remove, replace } = useFieldArray({ + control, + name: 'ecsMappingArray', + }); + + const formValue = watch(); + const ecsMappingArrayState = getFieldState('ecsMappingArray', formState); + const [osquerySchemaOptions, setOsquerySchemaOptions] = useState([]); + + useEffect(() => { + const subscription = watchRoot((data, payload) => { + if (payload.name === 'ecs_mapping') { + const parsedMapping = convertECSMappingToObject(formValue.ecsMappingArray); + if (!deepEqual(data.ecs_mapping, parsedMapping)) { + resetField('ecsMappingArray', { + defaultValue: [...convertECSMappingToArray(data.ecs_mapping), defaultEcsFormData], + }); + replace([...convertECSMappingToArray(data.ecs_mapping), defaultEcsFormData]); + } } - }, [fields, query, trigger]); + }); + + return () => subscription.unsubscribe(); + }, [watchRoot, ecsMapping, replace, resetField, formValue.ecsMappingArray]); - useEffect(() => { - if (!query?.length) { - return; + useEffect(() => { + const subscription = watch((data, payload) => { + if (data?.ecsMappingArray) { + const lastEcsIndex = data?.ecsMappingArray?.length - 1; + if (payload.name?.startsWith(`ecsMappingArray.${lastEcsIndex}.`)) { + const lastEcs = last(data.ecsMappingArray); + if (lastEcs?.key?.length && lastEcs?.result?.value?.length) { + append(defaultEcsFormData); + } + } } + }); + + return () => subscription.unsubscribe(); + }, [formValue, append, watch]); + + useEffect(() => { + if (!query?.length) { + return; + } + + const oneLineQuery = removeMultilines(query); - const oneLineQuery = removeMultilines(query); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let ast: Record | undefined; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let ast: Record | undefined; + try { + ast = sqliteParser(oneLineQuery)?.statement?.[0]; + } catch (e) { + return; + } - try { - ast = sqliteParser(oneLineQuery)?.statement?.[0]; - } catch (e) { - return; + const astOsqueryTables: Record< + string, + { + columns: OsqueryColumn[]; + order: number; } + > = + reduce( + ast, + (acc, data) => { + // select * from uptime + if (data?.type === 'identifier' && data?.variant === 'table') { + const osqueryTable = find(osquerySchema, ['name', data.name]); + + if (osqueryTable) { + acc[data.alias || data.name] = { + columns: osqueryTable.columns, + order: Object.keys(acc).length, + }; + } + } - const astOsqueryTables: Record< - string, - { - columns: OsqueryColumn[]; - order: number; - } - > = - reduce( - ast, - (acc, data) => { - // select * from uptime - if (data?.type === 'identifier' && data?.variant === 'table') { - const osqueryTable = find(osquerySchema, ['name', data.name]); + // select * from uptime, routes + if (data?.type === 'map' && data?.variant === 'join') { + if (data?.source?.type === 'identifier' && data?.source?.variant === 'table') { + const osqueryTable = find(osquerySchema, ['name', data?.source?.name]); if (osqueryTable) { - acc[data.alias || data.name] = { + acc[data?.source?.alias || data?.source?.name] = { columns: osqueryTable.columns, order: Object.keys(acc).length, }; } } - // select * from uptime, routes - if (data?.type === 'map' && data?.variant === 'join') { - if (data?.source?.type === 'identifier' && data?.source?.variant === 'table') { - const osqueryTable = find(osquerySchema, ['name', data?.source?.name]); + if (data?.source?.type === 'statement' && data?.source?.variant === 'compound') { + if ( + data?.source?.statement.from.type === 'identifier' && + data?.source?.statement.from.variant === 'table' + ) { + const osqueryTable = find(osquerySchema, [ + 'name', + data?.source?.statement.from.name, + ]); if (osqueryTable) { - acc[data?.source?.alias || data?.source?.name] = { + acc[data?.source?.statement.from.alias || data?.source?.statement.from.name] = { columns: osqueryTable.columns, order: Object.keys(acc).length, }; } } + } - if (data?.source?.type === 'statement' && data?.source?.variant === 'compound') { - if ( - data?.source?.statement.from.type === 'identifier' && - data?.source?.statement.from.variant === 'table' - ) { - const osqueryTable = find(osquerySchema, [ - 'name', - data?.source?.statement.from.name, - ]); - - if (osqueryTable) { - acc[data?.source?.statement.from.alias || data?.source?.statement.from.name] = { - columns: osqueryTable.columns, - order: Object.keys(acc).length, - }; - } - } - } - - each( - data?.map, - (mapValue: { - type: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - source: { type: string; variant: string; name: any | string; alias: any }; - }) => { - if (mapValue?.type === 'join') { - if ( - mapValue?.source?.type === 'identifier' && - mapValue?.source?.variant === 'table' - ) { - const osqueryTable = find(osquerySchema, ['name', mapValue?.source?.name]); - - if (osqueryTable) { - acc[mapValue?.source?.alias || mapValue?.source?.name] = { - columns: osqueryTable.columns, - order: Object.keys(acc).length, - }; - } + each( + data?.map, + (mapValue: { + type: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + source: { type: string; variant: string; name: any | string; alias: any }; + }) => { + if (mapValue?.type === 'join') { + if ( + mapValue?.source?.type === 'identifier' && + mapValue?.source?.variant === 'table' + ) { + const osqueryTable = find(osquerySchema, ['name', mapValue?.source?.name]); + + if (osqueryTable) { + acc[mapValue?.source?.alias || mapValue?.source?.name] = { + columns: osqueryTable.columns, + order: Object.keys(acc).length, + }; } } } - ); - } + } + ); + } - return acc; - }, - {} as Record< - string, - { - columns: OsqueryColumn[]; - order: number; - } - > - ) ?? {}; + return acc; + }, + {} as Record< + string, + { + columns: OsqueryColumn[]; + order: number; + } + > + ) ?? {}; - // Table doesn't exist in osquery schema - if (isEmpty(astOsqueryTables)) { - return; - } + // Table doesn't exist in osquery schema + if (isEmpty(astOsqueryTables)) { + return; + } - const suggestions = isArray(ast?.result) - ? ast?.result - ?.map((selectItem: { type: string; name: string; alias?: string }) => { - if (selectItem.type === 'identifier') { - /* + const suggestions = isArray(ast?.result) + ? ast?.result + ?.map((selectItem: { type: string; name: string; alias?: string }) => { + if (selectItem.type === 'identifier') { + /* select * from routes, uptime; */ - if (ast?.result.length === 1 && selectItem.name === '*') { - return reduce( - astOsqueryTables, - (acc, { columns: osqueryColumns, order: tableOrder }, table) => { - acc.push( - ...osqueryColumns.map((osqueryColumn) => ({ - label: osqueryColumn.name, - value: { - name: osqueryColumn.name, - description: osqueryColumn.description, - table, - tableOrder, - suggestion_label: osqueryColumn.name, - }, - })) - ); - - return acc; - }, - [] as OsquerySchemaOption[] - ); - } - - /* - select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid; - */ - - const [table, column] = selectItem.name.includes('.') - ? selectItem.name?.split('.') - : [Object.keys(astOsqueryTables)[0], selectItem.name]; - - if (column === '*' && astOsqueryTables[table]) { - const { columns: osqueryColumns, order: tableOrder } = astOsqueryTables[table]; - - return osqueryColumns.map((osqueryColumn) => ({ - label: osqueryColumn.name, - value: { - name: osqueryColumn.name, - description: osqueryColumn.description, - table, - tableOrder, - suggestion_label: `${osqueryColumn.name}`, - }, - })); - } - - if (astOsqueryTables[table]) { - const osqueryColumn = find(astOsqueryTables[table].columns, ['name', column]); - - if (osqueryColumn) { - const label = selectItem.alias ?? column; - - return [ - { - label, + if (ast?.result.length === 1 && selectItem.name === '*') { + return reduce( + astOsqueryTables, + (acc, { columns: osqueryColumns, order: tableOrder }, table) => { + acc.push( + ...osqueryColumns.map((osqueryColumn) => ({ + label: osqueryColumn.name, value: { name: osqueryColumn.name, description: osqueryColumn.description, table, - tableOrder: astOsqueryTables[table].order, - suggestion_label: `${label}`, + tableOrder, + suggestion_label: osqueryColumn.name, }, + })) + ); + + return acc; + }, + [] as OsquerySchemaOption[] + ); + } + + /* + select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid; + */ + + const [table, column] = selectItem.name.includes('.') + ? selectItem.name?.split('.') + : [Object.keys(astOsqueryTables)[0], selectItem.name]; + + if (column === '*' && astOsqueryTables[table]) { + const { columns: osqueryColumns, order: tableOrder } = astOsqueryTables[table]; + + return osqueryColumns.map((osqueryColumn) => ({ + label: osqueryColumn.name, + value: { + name: osqueryColumn.name, + description: osqueryColumn.description, + table, + tableOrder, + suggestion_label: `${osqueryColumn.name}`, + }, + })); + } + + if (astOsqueryTables[table]) { + const osqueryColumn = find(astOsqueryTables[table].columns, ['name', column]); + + if (osqueryColumn) { + const label = selectItem.alias ?? column; + + return [ + { + label, + value: { + name: osqueryColumn.name, + description: osqueryColumn.description, + table, + tableOrder: astOsqueryTables[table].order, + suggestion_label: `${label}`, }, - ]; - } + }, + ]; } } + } - /* + /* SELECT pid, uid, name, ROUND(( (user_time + system_time) / (cpu_time.tsb - cpu_time.itsb) ) * 100, 2) AS percentage @@ -945,100 +992,105 @@ export const ECSMappingEditorField = React.memo( LIMIT 5; */ - if (selectItem.type === 'function' && selectItem.alias) { - return [ - { - label: selectItem.alias, - value: { - name: selectItem.alias, - description: '', - table: '', - tableOrder: -1, - suggestion_label: selectItem.alias, - }, + if (selectItem.type === 'function' && selectItem.alias) { + return [ + { + label: selectItem.alias, + value: { + name: selectItem.alias, + description: '', + table: '', + tableOrder: -1, + suggestion_label: selectItem.alias, }, - ]; - } + }, + ]; + } - return []; - }) - .flat() - : []; + return []; + }) + .flat() + : []; - // Remove column duplicates by keeping the column from the table that appears last in the query - const newOptions = sortedUniqBy( - orderBy(suggestions, ['value.suggestion_label', 'value.tableOrder'], ['asc', 'desc']), - 'label' - ); - setOsquerySchemaOptions((prevValue) => - !deepEqual(prevValue, newOptions) ? newOptions : prevValue - ); - }, [query]); + // Remove column duplicates by keeping the column from the table that appears last in the query + const newOptions = sortedUniqBy( + orderBy(suggestions, ['value.suggestion_label', 'value.tableOrder'], ['asc', 'desc']), + 'label' + ); + setOsquerySchemaOptions((prevValue) => + !deepEqual(prevValue, newOptions) ? newOptions : prevValue + ); + }, [query]); - useEffect(() => { - const ecsList = formData?.ecs_mapping; - const lastEcs = formData?.ecs_mapping?.[itemsList?.current.length - 1]; + useEffect(() => { + const parsedMapping = convertECSMappingToObject(formValue.ecsMappingArray); + if (ecsMappingArrayState.isDirty && !deepEqual(parsedMapping, ecsMapping)) { + setValueRoot('ecs_mapping', parsedMapping, { + shouldTouch: true, + }); + } + }, [setValueRoot, formValue, ecsMappingArrayState.isDirty, ecsMapping]); - // we skip appending on remove - if (itemsList?.current?.length < ecsList?.length) { - return; + useEffect(() => { + if (!formState.isValid) { + const nonEmptyErrors = reject(ecsMappingArrayState.error, isEmpty) as InternalFieldErrors[]; + if (nonEmptyErrors.length) { + setError('ecs_mapping', { + type: nonEmptyErrors[0].key?.type ?? 'custom', + message: nonEmptyErrors[0].key?.message ?? '', + }); } + } else { + clearErrors('ecs_mapping'); + } + }, [ + errorsRoot, + clearErrors, + formState.isValid, + formState.errors, + setError, + ecsMappingArrayState.error, + ]); - // list contains ecs already, and the last item has values provided - if ( - (ecsList?.length === itemsList.current.length && - lastEcs?.key?.length && - lastEcs?.result?.value?.length) || - !fields?.length - ) { - return append(defaultEcsFormData); - } - }, [append, fields, formData]); - - return ( - <> - - - -
- -
-
- + return ( + <> + + + +
- - - - - - {fields.map((item, index, array) => { - itemsList.current = array; - - return ( -
- -
- ); - })} - - ); - }, - (prevProps, nextProps) => deepEqual(prevProps.euiFieldProps, nextProps.euiFieldProps) -); +
+
+ + + +
+
+ + + {fields.map((item, index, array) => ( +
+ +
+ ))} + + ); +}); // eslint-disable-next-line import/no-default-export export default ECSMappingEditorField; diff --git a/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx b/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx index ae3030d75154b..d709b4f639e6d 100644 --- a/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/query_flyout.tsx @@ -22,10 +22,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { FormProvider } from 'react-hook-form'; -import { isEmpty } from 'lodash'; -import { QueryIdField, IntervalField } from '../../form'; -import { defaultEcsFormData } from './ecs_mapping_editor_field'; -import { convertECSMappingToFormValue } from '../../../common/schemas/common/utils'; +import { DEFAULT_PLATFORM } from '../../../common/constants'; +import { QueryIdField, IntervalField, VersionField, ResultsTypeField } from '../../form'; import { CodeEditorField } from '../../saved_queries/form/code_editor_field'; import { PlatformCheckBoxGroupField } from './platform_checkbox_group_field'; import { ALL_OSQUERY_VERSIONS_OPTIONS } from './constants'; @@ -38,7 +36,6 @@ import { usePackQueryForm } from './use_pack_query_form'; import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown'; import { ECSMappingEditorField } from './lazy_ecs_mapping_editor_field'; import { useKibana } from '../../common/lib/kibana'; -import { VersionField } from '../../form'; interface QueryFlyoutProps { uniqueQueryIds: string[]; @@ -63,8 +60,7 @@ const QueryFlyoutComponent: React.FC = ({ const { handleSubmit, formState: { isSubmitting }, - setValue, - clearErrors, + resetField, } = hooksForm; const onSubmit = (payload: PackQueryFormData) => { const serializedData: PackSOQueryFormData = serializer(payload); @@ -75,22 +71,19 @@ const QueryFlyoutComponent: React.FC = ({ const handleSetQueryValue = useCallback( (savedQuery) => { if (savedQuery) { - clearErrors('id'); - setValue('id', savedQuery.id); - setValue('query', savedQuery.query); - // setValue('description', savedQuery.description); // TODO do we need it? - setValue('platform', savedQuery.platform ? savedQuery.platform : 'linux,windows,darwin'); - setValue('version', savedQuery.version ? [savedQuery.version] : []); - setValue('interval', savedQuery.interval); - setValue( - 'ecs_mapping', - !isEmpty(savedQuery.ecs_mapping) - ? convertECSMappingToFormValue(savedQuery.ecs_mapping) - : [defaultEcsFormData] - ); + resetField('id', { defaultValue: savedQuery.id }); + resetField('query', { defaultValue: savedQuery.query }); + resetField('platform', { + defaultValue: savedQuery.platform ? savedQuery.platform : DEFAULT_PLATFORM, + }); + resetField('version', { defaultValue: savedQuery.version ? [savedQuery.version] : [] }); + resetField('interval', { defaultValue: savedQuery.interval ? savedQuery.interval : 3600 }); + resetField('snapshot', { defaultValue: savedQuery.snapshot ?? true }); + resetField('removed'); + resetField('ecs_mapping', { defaultValue: savedQuery.ecs_mapping ?? {} }); } }, - [clearErrors, setValue] + [resetField] ); /* Avoids accidental closing of the flyout when the user clicks outside of the flyout */ const maskProps = useMemo(() => ({ onClick: () => ({}) }), []); @@ -151,6 +144,8 @@ const QueryFlyoutComponent: React.FC = ({ onCreateOption: undefined, }} /> + +
diff --git a/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx b/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx index 4a1e47c3df9b7..837398a35bf7e 100644 --- a/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx @@ -5,15 +5,12 @@ * 2.0. */ -import { isArray, isEmpty, map, xor } from 'lodash'; - +import { isArray, isEmpty, xor } from 'lodash'; import { useForm as useHookForm } from 'react-hook-form'; import type { Draft } from 'immer'; import { produce } from 'immer'; import { useMemo } from 'react'; -import { convertECSMappingToObject } from '../../../common/schemas/common/utils'; -import type { EcsMappingFormField } from './ecs_mapping_editor_field'; -import { defaultEcsFormData } from './ecs_mapping_editor_field'; +import type { ECSMapping } from '../../../common/schemas/common'; export interface UsePackQueryFormProps { uniqueQueryIds: string[]; @@ -24,9 +21,11 @@ export interface PackSOQueryFormData { id: string; query: string; interval: string; + snapshot?: boolean; + removed?: boolean; platform?: string | undefined; version?: string | undefined; - ecs_mapping?: PackQuerySOECSMapping[]; + ecs_mapping?: ECSMapping; } export type PackQuerySOECSMapping = Array<{ field: string; value: string }>; @@ -36,30 +35,23 @@ export interface PackQueryFormData { description?: string; query: string; interval: number; + snapshot?: boolean; + removed?: boolean; platform?: string | undefined; version?: string[] | undefined; - ecs_mapping: EcsMappingFormField[]; + ecs_mapping: ECSMapping; } -const deserializer = (payload: PackSOQueryFormData): PackQueryFormData => - ({ - id: payload.id, - query: payload.query, - interval: payload.interval ? parseInt(payload.interval, 10) : 3600, - platform: payload.platform, - version: payload.version ? [payload.version] : [], - ecs_mapping: !isEmpty(payload.ecs_mapping) - ? !isArray(payload.ecs_mapping) - ? map(payload.ecs_mapping as unknown as PackQuerySOECSMapping, (value, key) => ({ - key, - result: { - type: Object.keys(value)[0], - value: Object.values(value)[0], - }, - })) - : payload.ecs_mapping - : [defaultEcsFormData], - } as PackQueryFormData); +const deserializer = (payload: PackSOQueryFormData): PackQueryFormData => ({ + id: payload.id, + query: payload.query, + interval: payload.interval ? parseInt(payload.interval, 10) : 3600, + snapshot: payload.snapshot, + removed: payload.removed, + platform: payload.platform, + version: payload.version ? [payload.version] : [], + ecs_mapping: payload.ecs_mapping ?? {}, +}); const serializer = (payload: PackQueryFormData): PackSOQueryFormData => // @ts-expect-error update types @@ -86,9 +78,6 @@ const serializer = (payload: PackQueryFormData): PackSOQueryFormData => if (isEmpty(draft.ecs_mapping)) { delete draft.ecs_mapping; - } else { - // @ts-expect-error update types - draft.ecs_mapping = convertECSMappingToObject(payload.ecs_mapping); } return draft; @@ -110,7 +99,8 @@ export const usePackQueryForm = ({ uniqueQueryIds, defaultValue }: UsePackQueryF id: '', query: '', interval: 3600, - ecs_mapping: [defaultEcsFormData], + snapshot: true, + removed: false, }, }), }; diff --git a/x-pack/plugins/osquery/public/packs/types.ts b/x-pack/plugins/osquery/public/packs/types.ts index dcdb03045ab22..941d4f400042d 100644 --- a/x-pack/plugins/osquery/public/packs/types.ts +++ b/x-pack/plugins/osquery/public/packs/types.ts @@ -10,7 +10,7 @@ import type { PackQueryFormData } from './queries/use_pack_query_form'; export type PackSavedObject = SavedObject<{ name: string; description: string | undefined; - queries: PackQueryFormData[]; + queries: Record>; version?: number; enabled: boolean | undefined; created_at: string; diff --git a/x-pack/plugins/osquery/public/packs/use_create_pack.ts b/x-pack/plugins/osquery/public/packs/use_create_pack.ts index 26cf1fad2eeb9..578e80c7234a2 100644 --- a/x-pack/plugins/osquery/public/packs/use_create_pack.ts +++ b/x-pack/plugins/osquery/public/packs/use_create_pack.ts @@ -13,7 +13,7 @@ import { PLUGIN_ID } from '../../common'; import { pagePathGetters } from '../common/page_paths'; import { PACKS_ID } from './constants'; import { useErrorToast } from '../common/hooks/use_error_toast'; -import type { PackSavedObject } from './types'; +import type { PackItem, PackSavedObject } from './types'; interface UseCreatePackProps { withRedirect?: boolean; @@ -31,7 +31,7 @@ export const useCreatePack = ({ withRedirect }: UseCreatePackProps) => { return useMutation< { data: PackSavedObject }, { body: { error: string; message: string } }, - PackSavedObject + Omit >( (payload) => http.post('/api/osquery/packs', { diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx index 86426d432701c..e6f792b5c5423 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx @@ -20,6 +20,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { useHistory } from 'react-router-dom'; +import deepEqual from 'fast-deep-equal'; import type { SavedObject } from '@kbn/core/public'; import { Direction } from '../../../../common/search_strategy'; @@ -76,7 +77,7 @@ const PlayButtonComponent: React.FC = ({ disabled = false, save ); }; -const PlayButton = React.memo(PlayButtonComponent); +const PlayButton = React.memo(PlayButtonComponent, deepEqual); interface EditButtonProps { disabled?: boolean; diff --git a/x-pack/plugins/osquery/public/saved_queries/form/index.tsx b/x-pack/plugins/osquery/public/saved_queries/form/index.tsx index 6bddd7f0508e4..8ea39cc8d5208 100644 --- a/x-pack/plugins/osquery/public/saved_queries/form/index.tsx +++ b/x-pack/plugins/osquery/public/saved_queries/form/index.tsx @@ -17,7 +17,13 @@ import React, { useCallback, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { IntervalField, QueryIdField, QueryDescriptionField, VersionField } from '../../form'; +import { + IntervalField, + QueryIdField, + QueryDescriptionField, + VersionField, + ResultsTypeField, +} from '../../form'; import { PlatformCheckBoxGroupField } from '../../packs/queries/platform_checkbox_group_field'; import { ALL_OSQUERY_VERSIONS_OPTIONS } from '../../packs/queries/constants'; import { ECSMappingEditorField } from '../../packs/queries/lazy_ecs_mapping_editor_field'; @@ -92,7 +98,10 @@ const SavedQueryFormComponent: React.FC = ({ - Test configuration + @@ -122,6 +131,8 @@ const SavedQueryFormComponent: React.FC = ({ + + diff --git a/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx b/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx index f8a99cf0e97a4..d2b1f41525327 100644 --- a/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx +++ b/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx @@ -11,10 +11,6 @@ import type { Draft } from 'immer'; import produce from 'immer'; import { useMemo } from 'react'; import type { ECSMapping } from '../../../common/schemas/common'; -import { convertECSMappingToObject } from '../../../common/schemas/common/utils'; -import type { EcsMappingFormField } from '../../packs/queries/ecs_mapping_editor_field'; -import { defaultEcsFormData } from '../../packs/queries/ecs_mapping_editor_field'; - import { useSavedQueries } from '../use_saved_queries'; export interface SavedQuerySOFormData { @@ -22,6 +18,8 @@ export interface SavedQuerySOFormData { description?: string; query?: string; interval?: string; + snapshot?: boolean; + removed?: boolean; platform?: string; version?: string | undefined; ecs_mapping?: ECSMapping | undefined; @@ -32,9 +30,11 @@ export interface SavedQueryFormData { description?: string; query?: string; interval?: number; + snapshot?: boolean; + removed?: boolean; platform?: string; version?: string[]; - ecs_mapping: EcsMappingFormField[]; + ecs_mapping: ECSMapping | undefined; } interface UseSavedQueryFormProps { @@ -46,17 +46,11 @@ const deserializer = (payload: SavedQuerySOFormData): SavedQueryFormData => ({ description: payload.description, query: payload.query, interval: payload.interval ? parseInt(payload.interval, 10) : 3600, + snapshot: payload.snapshot, + removed: payload.removed, platform: payload.platform, version: payload.version ? [payload.version] : [], - ecs_mapping: !isEmpty(payload.ecs_mapping) - ? (map(payload.ecs_mapping, (value, key: string) => ({ - key, - result: { - type: Object.keys(value)[0], - value: Object.values(value)[0], - }, - })) as unknown as EcsMappingFormField[]) - : [defaultEcsFormData], + ecs_mapping: !isEmpty(payload.ecs_mapping) ? payload.ecs_mapping : {}, }); export const savedQueryDataSerializer = (payload: SavedQueryFormData): SavedQuerySOFormData => @@ -74,12 +68,15 @@ export const savedQueryDataSerializer = (payload: SavedQueryFormData): SavedQuer delete draft.platform; } - draft.ecs_mapping = convertECSMappingToObject(payload.ecs_mapping); - if (draft.interval) { draft.interval = draft.interval + ''; } + if (draft.snapshot) { + delete draft.snapshot; + delete draft.removed; + } + return draft; }); @@ -103,7 +100,7 @@ export const useSavedQueryForm = ({ defaultValue }: UseSavedQueryFormProps) => { id: '', query: '', interval: 3600, - ecs_mapping: [defaultEcsFormData], + ecs_mapping: {}, }, }), }; diff --git a/x-pack/plugins/osquery/public/saved_queries/saved_query_flyout.tsx b/x-pack/plugins/osquery/public/saved_queries/saved_query_flyout.tsx index abf8138ff11fa..130f4591ef18f 100644 --- a/x-pack/plugins/osquery/public/saved_queries/saved_query_flyout.tsx +++ b/x-pack/plugins/osquery/public/saved_queries/saved_query_flyout.tsx @@ -54,8 +54,6 @@ const SavedQueryFlyoutComponent: React.FC = ({ const onSubmit = useCallback( async (payload: SavedQueryFormData) => { const serializedData = serializer(payload); - // TODO CHECK THIS - // @ts-expect-error update types await createSavedQueryMutation.mutateAsync(serializedData).then(() => onClose()); }, [createSavedQueryMutation, onClose, serializer] diff --git a/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts b/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts index 0d96e4a118736..e4d4619beeee0 100644 --- a/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts +++ b/x-pack/plugins/osquery/public/saved_queries/use_create_saved_query.ts @@ -14,6 +14,7 @@ import { pagePathGetters } from '../common/page_paths'; import { SAVED_QUERIES_ID } from './constants'; import { useErrorToast } from '../common/hooks/use_error_toast'; import type { SavedQuerySO } from '../routes/saved_queries/list'; +import type { SavedQuerySOFormData } from './form/use_saved_query_form'; interface UseCreateSavedQueryProps { withRedirect?: boolean; @@ -28,7 +29,11 @@ export const useCreateSavedQuery = ({ withRedirect }: UseCreateSavedQueryProps) } = useKibana().services; const setErrorToast = useErrorToast(); - return useMutation<{ data: SavedQuerySO }, { body: { error: string; message: string } }>( + return useMutation< + { data: SavedQuerySO }, + { body: { error: string; message: string } }, + SavedQuerySOFormData + >( (payload) => http.post('/api/osquery/saved_queries', { body: JSON.stringify(payload), diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx index 76664f20b9b98..89e92d167d01d 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx @@ -6,21 +6,14 @@ */ import React, { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'; - import { EuiSpacer } from '@elastic/eui'; - import uuid from 'uuid'; import { useForm as useHookForm, FormProvider } from 'react-hook-form'; import { get, isEmpty, map } from 'lodash'; import useEffectOnce from 'react-use/lib/useEffectOnce'; -import { - convertECSMappingToFormValue, - convertECSMappingToObject, -} from '../../../common/schemas/common/utils'; +import type { ECSMapping } from '../../../common/schemas/common/utils'; import { QueryPackSelectable } from '../../live_queries/form/query_pack_selectable'; -import type { EcsMappingFormField } from '../../packs/queries/ecs_mapping_editor_field'; -import { defaultEcsFormData } from '../../packs/queries/ecs_mapping_editor_field'; import { useFormContext } from '../../shared_imports'; import type { ArrayItem } from '../../shared_imports'; import { useKibana } from '../../common/lib/kibana'; @@ -43,28 +36,28 @@ interface ResponseActionValidatorRef { interface OsqueryResponseActionsParamsFormFields { savedQueryId: string | null; id: string; - ecs_mapping: EcsMappingFormField[]; + ecs_mapping: ECSMapping; query: string; packId?: string[]; queries?: Array<{ id: string; - ecs_mapping: EcsMappingFormField[]; + ecs_mapping: ECSMapping; query: string; }>; } -const OsqueryResponseActionParamsFormComponent: React.ForwardRefExoticComponent< - React.PropsWithoutRef & - React.RefAttributes -> = forwardRef(({ item }, ref) => { +const OsqueryResponseActionParamsFormComponent = forwardRef< + ResponseActionValidatorRef, + OsqueryResponseActionsParamsFormProps +>(({ item }, ref) => { const uniqueId = useMemo(() => uuid.v4(), []); const hooksForm = useHookForm({ defaultValues: { - ecs_mapping: [defaultEcsFormData], + ecs_mapping: {}, id: uniqueId, }, }); - // + const { watch, setValue, register, clearErrors, formState, handleSubmit } = hooksForm; const { errors, isValid } = formState; const context = useFormContext(); @@ -105,7 +98,7 @@ const OsqueryResponseActionParamsFormComponent: React.ForwardRefExoticComponent< id: watchedValues.id, savedQueryId: watchedValues.savedQueryId, query: watchedValues.query, - ecs_mapping: convertECSMappingToObject(watchedValues.ecs_mapping), + ecs_mapping: watchedValues.ecs_mapping, }, }, }); @@ -146,16 +139,12 @@ const OsqueryResponseActionParamsFormComponent: React.ForwardRefExoticComponent< useEffectOnce(() => { if (defaultParams && defaultParams.id) { - const { packId, ecs_mapping: ecsMapping, ...restParams } = defaultParams; + const { packId, ...restParams } = defaultParams; map(restParams, (value, key: keyof OsqueryResponseActionsParamsFormFields) => { if (!isEmpty(value)) { setValue(key, value); } }); - if (ecsMapping) { - const converted = convertECSMappingToFormValue(ecsMapping); - setValue('ecs_mapping', converted); - } if (!isEmpty(packId)) { setValue('packId', [packId]); @@ -167,7 +156,7 @@ const OsqueryResponseActionParamsFormComponent: React.ForwardRefExoticComponent< setValue('packId', []); setValue('savedQueryId', ''); setValue('query', ''); - setValue('ecs_mapping', [defaultEcsFormData]); + setValue('ecs_mapping', {}); clearErrors(); }, [clearErrors, setValue]); diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/pack_field_wrapper.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/pack_field_wrapper.tsx index a70a046ec4219..54df22217bb16 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/pack_field_wrapper.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/pack_field_wrapper.tsx @@ -10,7 +10,7 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { find } from 'lodash'; import { useWatch } from 'react-hook-form'; -import type { EcsMappingFormField } from '../../packs/queries/ecs_mapping_editor_field'; +import type { ECSMapping } from '../../../common/schemas/common'; import { PackQueriesStatusTable } from '../../live_queries/form/pack_queries_status_table'; import { usePacks } from '../../packs/use_packs'; import { PacksComboBoxField } from '../../live_queries/form/packs_combobox_field'; @@ -20,7 +20,7 @@ interface PackFieldWrapperProps { queries?: Array<{ id: string; query: string; - ecs_mapping?: EcsMappingFormField[]; + ecs_mapping?: ECSMapping; }>; action_id?: string; agents?: string[]; @@ -39,7 +39,7 @@ export const PackFieldWrapper = ({ showResultsHeader, }: PackFieldWrapperProps) => { const { data: packsData } = usePacks({}); - const { packId } = useWatch() as unknown as { packId: string[] }; + const { packId } = useWatch<{ packId: string[] }>(); const selectedPackData = useMemo( () => (packId?.length ? find(packsData?.data, { id: packId[0] }) : null), @@ -55,7 +55,7 @@ export const PackFieldWrapper = ({ {submitButtonContent} @@ -67,6 +67,7 @@ export const PackFieldWrapper = ({ ; }>; version?: number; @@ -40,6 +42,8 @@ export interface SavedQuerySavedObjectAttributes { description: string | undefined; query: string; interval: number | string; + snapshot?: boolean; + removed?: boolean; platform: string; ecs_mapping?: Array>; created_at: string; diff --git a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts index dccbd77f0505f..c915b15e603f5 100644 --- a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts +++ b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts @@ -33,6 +33,7 @@ export const usageMetricType: SavedObjectsType = { }; export const savedQuerySavedObjectMappings: SavedObjectsType['mappings'] = { + dynamic: false, properties: { description: { type: 'text', @@ -126,6 +127,7 @@ export const packSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'long', }, queries: { + dynamic: false, properties: { id: { type: 'keyword', @@ -194,6 +196,7 @@ export const packAssetSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'long', }, queries: { + dynamic: false, properties: { id: { type: 'keyword', diff --git a/x-pack/plugins/osquery/server/lib/telemetry/filters.ts b/x-pack/plugins/osquery/server/lib/telemetry/filters.ts index 513242ffb583d..fd2c6536a126e 100644 --- a/x-pack/plugins/osquery/server/lib/telemetry/filters.ts +++ b/x-pack/plugins/osquery/server/lib/telemetry/filters.ts @@ -19,6 +19,8 @@ export const savedQueryEventFields: AllowlistFields = { platform: true, version: true, interval: true, + snapshot: true, + removed: true, ecs_mapping: true, }; diff --git a/x-pack/plugins/osquery/server/lib/telemetry/helpers.ts b/x-pack/plugins/osquery/server/lib/telemetry/helpers.ts index b9ceb105c39ed..0754ebc74bd5f 100644 --- a/x-pack/plugins/osquery/server/lib/telemetry/helpers.ts +++ b/x-pack/plugins/osquery/server/lib/telemetry/helpers.ts @@ -63,6 +63,8 @@ export const templateSavedQueries = ( interval: isString(item.attributes.interval) ? parseInt(item.attributes.interval, 10) : item.attributes.interval, + ...(!isEmpty(item.attributes.snapshot) ? { snapshot: item.attributes.snapshot } : {}), + ...(!isEmpty(item.attributes.removed) ? { snapshot: item.attributes.removed } : {}), ...(!isEmpty(item.attributes.ecs_mapping) ? { ecs_mapping: item.attributes.ecs_mapping } : {}), prebuilt: prebuiltSavedQueryIds.includes(item.id), })); diff --git a/x-pack/plugins/osquery/server/lib/telemetry/sender.ts b/x-pack/plugins/osquery/server/lib/telemetry/sender.ts index d9bce6f9166e4..512cf874a1781 100644 --- a/x-pack/plugins/osquery/server/lib/telemetry/sender.ts +++ b/x-pack/plugins/osquery/server/lib/telemetry/sender.ts @@ -199,6 +199,18 @@ export class TelemetryEventsSender { optional: true, }, }, + snapshot: { + type: 'boolean', + _meta: { + description: '', + }, + }, + removed: { + type: 'boolean', + _meta: { + description: '', + }, + }, prebuilt: { type: 'boolean', _meta: { diff --git a/x-pack/plugins/osquery/server/routes/pack/create_pack_route.ts b/x-pack/plugins/osquery/server/routes/pack/create_pack_route.ts index 5f5cd40e815d8..c60c6d476974b 100644 --- a/x-pack/plugins/osquery/server/routes/pack/create_pack_route.ts +++ b/x-pack/plugins/osquery/server/routes/pack/create_pack_route.ts @@ -39,6 +39,8 @@ export const createPackRoute = (router: IRouter, osqueryContext: OsqueryAppConte schema.object({ query: schema.string(), interval: schema.maybe(schema.number()), + snapshot: schema.maybe(schema.boolean()), + removed: schema.maybe(schema.boolean()), platform: schema.maybe(schema.string()), version: schema.maybe(schema.string()), ecs_mapping: schema.maybe( diff --git a/x-pack/plugins/osquery/server/routes/pack/update_pack_route.ts b/x-pack/plugins/osquery/server/routes/pack/update_pack_route.ts index 0afdbe6dd005a..c113cbeb36c32 100644 --- a/x-pack/plugins/osquery/server/routes/pack/update_pack_route.ts +++ b/x-pack/plugins/osquery/server/routes/pack/update_pack_route.ts @@ -47,6 +47,8 @@ export const updatePackRoute = (router: IRouter, osqueryContext: OsqueryAppConte schema.object({ query: schema.string(), interval: schema.maybe(schema.number()), + snapshot: schema.maybe(schema.boolean()), + removed: schema.maybe(schema.boolean()), platform: schema.maybe(schema.string()), version: schema.maybe(schema.string()), ecs_mapping: schema.maybe( diff --git a/x-pack/plugins/osquery/server/routes/pack/utils.test.ts b/x-pack/plugins/osquery/server/routes/pack/utils.test.ts index 97905fde6bf02..05aff28073937 100644 --- a/x-pack/plugins/osquery/server/routes/pack/utils.test.ts +++ b/x-pack/plugins/osquery/server/routes/pack/utils.test.ts @@ -33,7 +33,6 @@ const getTestQueries = (additionalFields?: Record, packName = ' const oneLiner = { default: { - ecs_mapping: {}, interval: 3600, query: `select u.username, p.pid, p.name, pos.local_address, pos.local_port, p.path, p.cmdline, pos.remote_address, pos.remote_port from processes as p join users as u on u.uid=p.uid join process_open_sockets as pos on pos.pid=p.pid where pos.remote_port !='0' limit 1000;`, }, @@ -43,7 +42,7 @@ describe('Pack utils', () => { describe('convertSOQueriesToPack', () => { test('converts to pack with empty ecs_mapping', () => { const convertedQueries = convertSOQueriesToPack(getTestQueries()); - expect(convertedQueries).toStrictEqual(getTestQueries({ ecs_mapping: {} })); + expect(convertedQueries).toStrictEqual(getTestQueries({})); }); test('converts to pack with converting query to single line', () => { const convertedQueries = convertSOQueriesToPack(getTestQueries(), { removeMultiLines: true }); @@ -51,7 +50,7 @@ describe('Pack utils', () => { }); test('converts to object with pack names after query.id', () => { const convertedQueries = convertSOQueriesToPack(getTestQueries({ id: 'testId' })); - expect(convertedQueries).toStrictEqual(getTestQueries({ ecs_mapping: {} }, 'testId')); + expect(convertedQueries).toStrictEqual(getTestQueries({}, 'testId')); }); }); }); diff --git a/x-pack/plugins/osquery/server/routes/pack/utils.ts b/x-pack/plugins/osquery/server/routes/pack/utils.ts index b4c1bdfa85373..fe1ded84f4466 100644 --- a/x-pack/plugins/osquery/server/routes/pack/utils.ts +++ b/x-pack/plugins/osquery/server/routes/pack/utils.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { pick, reduce } from 'lodash'; +import { isEmpty, pick, reduce } from 'lodash'; +import { DEFAULT_PLATFORM } from '../../../common/constants'; import { removeMultilines } from '../../../common/utils/build_query/remove_multilines'; import { convertECSMappingToArray, convertECSMappingToObject } from '../utils'; @@ -18,6 +19,8 @@ export const convertPackQueriesToSO = (queries) => acc.push({ id: key, ...pick(value, ['name', 'query', 'interval', 'platform', 'version']), + ...(value.snapshot !== undefined ? { snapshot: value.snapshot } : {}), + ...(value.removed !== undefined ? { removed: value.removed } : {}), ...(ecsMapping ? { ecs_mapping: ecsMapping } : {}), }); @@ -28,6 +31,8 @@ export const convertPackQueriesToSO = (queries) => name: string; query: string; interval: number; + snapshot?: boolean; + removed?: boolean; ecs_mapping?: Record; }> ); @@ -37,12 +42,13 @@ export const convertSOQueriesToPack = (queries, options?: { removeMultiLines?: b reduce( queries, // eslint-disable-next-line @typescript-eslint/naming-convention - (acc, { id: queryId, ecs_mapping, query, ...rest }, key) => { + (acc, { id: queryId, ecs_mapping, query, platform, ...rest }, key) => { const index = queryId ? queryId : key; acc[index] = { ...rest, query: options?.removeMultiLines ? removeMultilines(query) : query, - ecs_mapping: convertECSMappingToObject(ecs_mapping), + ...(!isEmpty(ecs_mapping) ? { ecs_mapping: convertECSMappingToObject(ecs_mapping) } : {}), + ...(platform === DEFAULT_PLATFORM || platform === undefined ? {} : { platform }), }; return acc; diff --git a/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts index 8ee9cef33477f..206719927281b 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts @@ -31,8 +31,18 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp const coreContext = await context.core; const savedObjectsClient = coreContext.savedObjects.client; - // eslint-disable-next-line @typescript-eslint/naming-convention - const { id, description, platform, query, version, interval, ecs_mapping } = request.body; + const { + id, + description, + platform, + query, + version, + interval, + snapshot, + removed, + // eslint-disable-next-line @typescript-eslint/naming-convention + ecs_mapping, + } = request.body; const currentUser = await osqueryContext.security.authc.getCurrentUser(request)?.username; @@ -58,13 +68,15 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp platform, version, interval, + snapshot, + removed, ecs_mapping: convertECSMappingToArray(ecs_mapping), created_by: currentUser, created_at: new Date().toISOString(), updated_by: currentUser, updated_at: new Date().toISOString(), }, - (value) => !isEmpty(value) + (value) => !isEmpty(value) || value === false ) ); diff --git a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts index df1647ebc8d37..b83787794c2b7 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts @@ -29,6 +29,8 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp query: schema.string(), description: schema.maybe(schema.string()), interval: schema.maybe(schema.number()), + snapshot: schema.maybe(schema.boolean()), + removed: schema.maybe(schema.boolean()), platform: schema.maybe(schema.string()), version: schema.maybe(schema.string()), ecs_mapping: schema.maybe( @@ -60,6 +62,8 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp query, version, interval, + snapshot, + removed, // eslint-disable-next-line @typescript-eslint/naming-convention ecs_mapping, } = request.body; @@ -97,6 +101,8 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp query, version, interval, + snapshot, + removed, ecs_mapping: convertECSMappingToArray(ecs_mapping), updated_by: currentUser, updated_at: new Date().toISOString(), diff --git a/x-pack/plugins/rule_registry/common/index.ts b/x-pack/plugins/rule_registry/common/index.ts index 1f6053735d9b7..6c12d82cb95eb 100644 --- a/x-pack/plugins/rule_registry/common/index.ts +++ b/x-pack/plugins/rule_registry/common/index.ts @@ -11,3 +11,4 @@ export type { RuleRegistrySearchRequestPagination, } from './search_strategy'; export { BASE_RAC_ALERTS_API_PATH } from './constants'; +export type { BrowserFields, BrowserField } from './types'; diff --git a/x-pack/plugins/rule_registry/common/types.ts b/x-pack/plugins/rule_registry/common/types.ts index d1c5b6706c391..fd238b66c82bb 100644 --- a/x-pack/plugins/rule_registry/common/types.ts +++ b/x-pack/plugins/rule_registry/common/types.ts @@ -9,6 +9,9 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as t from 'io-ts'; +import type { IFieldSubType } from '@kbn/es-query'; +import type { RuntimeField } from '@kbn/data-views-plugin/common'; + // note: these schemas are not exhaustive. See the `Sort` type of `@elastic/elasticsearch` if you need to enhance it. const fieldSchema = t.string; export const sortOrderSchema = t.union([t.literal('asc'), t.literal('desc'), t.literal('_doc')]); @@ -302,3 +305,21 @@ export interface ClusterPutComponentTemplateBody { mappings: estypes.MappingTypeMapping; }; } + +export interface BrowserField { + aggregatable: boolean; + category: string; + description?: string | null; + example?: string | number | null; + fields: Readonly>>; + format?: string; + indexes: string[]; + name: string; + searchable: boolean; + type: string; + subType?: IFieldSubType; + readFromDocValues: boolean; + runtimeField?: RuntimeField; +} + +export type BrowserFields = Record>; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 31731cecbeccb..3727675d99852 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -31,6 +31,7 @@ import { import { Logger, ElasticsearchClient, EcsEventOutcome } from '@kbn/core/server'; import { AuditLogger } from '@kbn/security-plugin/server'; import { IndexPatternsFetcher } from '@kbn/data-plugin/server'; +import { BrowserFields } from '../../common'; import { alertAuditEvent, operationAlertAuditActionMap } from './audit_events'; import { ALERT_WORKFLOW_STATUS, @@ -42,7 +43,6 @@ import { ParsedTechnicalFields } from '../../common/parse_technical_fields'; import { Dataset, IRuleDataService } from '../rule_data_plugin_service'; import { getAuthzFilter, getSpacesFilter } from '../lib'; import { fieldDescriptorToBrowserFieldMapper } from './browser_fields'; -import { BrowserFields } from '../types'; // TODO: Fix typings https://github.com/elastic/kibana/issues/101776 type NonNullableProps = Omit & { diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts b/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts index 074c3f60006c8..e0327495dba2d 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts @@ -6,7 +6,7 @@ */ import { FieldDescriptor } from '@kbn/data-views-plugin/server'; -import { BrowserField, BrowserFields } from '../../types'; +import { BrowserFields, BrowserField } from '../../../common'; const getFieldCategory = (fieldCapability: FieldDescriptor) => { const name = fieldCapability.name.split('.'); @@ -21,7 +21,7 @@ const getFieldCategory = (fieldCapability: FieldDescriptor) => { const browserFieldFactory = ( fieldCapability: FieldDescriptor, category: string -): { [fieldName in string]: BrowserField } => { +): Readonly>> => { return { [fieldCapability.name]: { ...fieldCapability, diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts index 6b2d59c824ab3..44789b06d2123 100644 --- a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts @@ -9,6 +9,7 @@ import { IRouter } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import * as t from 'io-ts'; +import { BrowserFields } from '../../common'; import { RacRequestHandlerContext } from '../types'; import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; import { buildRouteValidation } from './utils/route_validation'; @@ -50,7 +51,7 @@ export const getBrowserFieldsByFeatureId = (router: IRouter; - -export type BrowserField = FieldSpec & { - category: string; -}; - -export type BrowserFields = { - [category in string]: { fields: { [fieldName in string]: BrowserField } }; -}; diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/saved_object.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/saved_object.ts index 330eebc1602b4..3ba81321ca9ee 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/saved_object.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/saved_object.ts @@ -24,6 +24,7 @@ const writeOperations: string[] = [ 'update', 'bulk_update', 'delete', + 'bulk_delete', 'share_to_space', ]; const allOperations: string[] = [...readOperations, ...writeOperations]; diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts index d9c82403a582a..1a8d7814e5a38 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts @@ -109,6 +109,7 @@ describe('features', () => { actions.savedObject.get('all-savedObject-all-1', 'update'), actions.savedObject.get('all-savedObject-all-1', 'bulk_update'), actions.savedObject.get('all-savedObject-all-1', 'delete'), + actions.savedObject.get('all-savedObject-all-1', 'bulk_delete'), actions.savedObject.get('all-savedObject-all-1', 'share_to_space'), actions.savedObject.get('all-savedObject-all-2', 'bulk_get'), actions.savedObject.get('all-savedObject-all-2', 'get'), @@ -120,6 +121,7 @@ describe('features', () => { actions.savedObject.get('all-savedObject-all-2', 'update'), actions.savedObject.get('all-savedObject-all-2', 'bulk_update'), actions.savedObject.get('all-savedObject-all-2', 'delete'), + actions.savedObject.get('all-savedObject-all-2', 'bulk_delete'), actions.savedObject.get('all-savedObject-all-2', 'share_to_space'), actions.savedObject.get('all-savedObject-read-1', 'bulk_get'), actions.savedObject.get('all-savedObject-read-1', 'get'), @@ -148,6 +150,7 @@ describe('features', () => { actions.savedObject.get('read-savedObject-all-1', 'update'), actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), actions.savedObject.get('read-savedObject-all-1', 'delete'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_delete'), actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), actions.savedObject.get('read-savedObject-all-2', 'get'), @@ -159,6 +162,7 @@ describe('features', () => { actions.savedObject.get('read-savedObject-all-2', 'update'), actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), actions.savedObject.get('read-savedObject-all-2', 'delete'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_delete'), actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), actions.savedObject.get('read-savedObject-read-1', 'get'), @@ -301,6 +305,7 @@ describe('features', () => { actions.savedObject.get('all-savedObject-all-1', 'update'), actions.savedObject.get('all-savedObject-all-1', 'bulk_update'), actions.savedObject.get('all-savedObject-all-1', 'delete'), + actions.savedObject.get('all-savedObject-all-1', 'bulk_delete'), actions.savedObject.get('all-savedObject-all-1', 'share_to_space'), actions.savedObject.get('all-savedObject-all-2', 'bulk_get'), actions.savedObject.get('all-savedObject-all-2', 'get'), @@ -312,6 +317,7 @@ describe('features', () => { actions.savedObject.get('all-savedObject-all-2', 'update'), actions.savedObject.get('all-savedObject-all-2', 'bulk_update'), actions.savedObject.get('all-savedObject-all-2', 'delete'), + actions.savedObject.get('all-savedObject-all-2', 'bulk_delete'), actions.savedObject.get('all-savedObject-all-2', 'share_to_space'), actions.savedObject.get('all-savedObject-read-1', 'bulk_get'), actions.savedObject.get('all-savedObject-read-1', 'get'), @@ -339,6 +345,7 @@ describe('features', () => { actions.savedObject.get('read-savedObject-all-1', 'update'), actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), actions.savedObject.get('read-savedObject-all-1', 'delete'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_delete'), actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), actions.savedObject.get('read-savedObject-all-2', 'get'), @@ -350,6 +357,7 @@ describe('features', () => { actions.savedObject.get('read-savedObject-all-2', 'update'), actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), actions.savedObject.get('read-savedObject-all-2', 'delete'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_delete'), actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), actions.savedObject.get('read-savedObject-read-1', 'get'), @@ -427,6 +435,7 @@ describe('features', () => { actions.savedObject.get('read-savedObject-all-1', 'update'), actions.savedObject.get('read-savedObject-all-1', 'bulk_update'), actions.savedObject.get('read-savedObject-all-1', 'delete'), + actions.savedObject.get('read-savedObject-all-1', 'bulk_delete'), actions.savedObject.get('read-savedObject-all-1', 'share_to_space'), actions.savedObject.get('read-savedObject-all-2', 'bulk_get'), actions.savedObject.get('read-savedObject-all-2', 'get'), @@ -438,6 +447,7 @@ describe('features', () => { actions.savedObject.get('read-savedObject-all-2', 'update'), actions.savedObject.get('read-savedObject-all-2', 'bulk_update'), actions.savedObject.get('read-savedObject-all-2', 'delete'), + actions.savedObject.get('read-savedObject-all-2', 'bulk_delete'), actions.savedObject.get('read-savedObject-all-2', 'share_to_space'), actions.savedObject.get('read-savedObject-read-1', 'bulk_get'), actions.savedObject.get('read-savedObject-read-1', 'get'), @@ -732,6 +742,7 @@ describe('reserved', () => { actions.savedObject.get('savedObject-all-1', 'update'), actions.savedObject.get('savedObject-all-1', 'bulk_update'), actions.savedObject.get('savedObject-all-1', 'delete'), + actions.savedObject.get('savedObject-all-1', 'bulk_delete'), actions.savedObject.get('savedObject-all-1', 'share_to_space'), actions.savedObject.get('savedObject-all-2', 'bulk_get'), actions.savedObject.get('savedObject-all-2', 'get'), @@ -743,6 +754,7 @@ describe('reserved', () => { actions.savedObject.get('savedObject-all-2', 'update'), actions.savedObject.get('savedObject-all-2', 'bulk_update'), actions.savedObject.get('savedObject-all-2', 'delete'), + actions.savedObject.get('savedObject-all-2', 'bulk_delete'), actions.savedObject.get('savedObject-all-2', 'share_to_space'), actions.savedObject.get('savedObject-read-1', 'bulk_get'), actions.savedObject.get('savedObject-read-1', 'get'), @@ -862,6 +874,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -993,6 +1006,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1015,6 +1029,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1044,6 +1059,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1081,6 +1097,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1104,6 +1121,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1127,6 +1145,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1149,6 +1168,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1227,6 +1247,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1249,6 +1270,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1278,6 +1300,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1384,6 +1407,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1406,6 +1430,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1455,6 +1480,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1484,6 +1510,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1567,6 +1594,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1589,6 +1617,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1709,6 +1738,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1738,6 +1768,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1775,6 +1806,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1798,6 +1830,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1821,6 +1854,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1843,6 +1877,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1941,6 +1976,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -1970,6 +2006,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2007,6 +2044,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2030,6 +2068,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2053,6 +2092,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2075,6 +2115,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2173,6 +2214,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-licensed-sub-feature-type', 'get'), @@ -2184,6 +2226,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-licensed-sub-feature-type', 'update'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-licensed-sub-feature-type', 'delete'), + actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-licensed-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2219,6 +2262,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-licensed-sub-feature-type', 'get'), @@ -2230,6 +2274,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-licensed-sub-feature-type', 'update'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-licensed-sub-feature-type', 'delete'), + actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-licensed-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2273,6 +2318,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-licensed-sub-feature-type', 'get'), @@ -2284,6 +2330,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-licensed-sub-feature-type', 'update'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-licensed-sub-feature-type', 'delete'), + actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-licensed-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2313,6 +2360,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-licensed-sub-feature-type', 'get'), @@ -2324,6 +2372,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-licensed-sub-feature-type', 'update'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-licensed-sub-feature-type', 'delete'), + actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-licensed-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2353,6 +2402,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-licensed-sub-feature-type', 'get'), @@ -2364,6 +2414,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-licensed-sub-feature-type', 'update'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-licensed-sub-feature-type', 'delete'), + actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-licensed-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), @@ -2392,6 +2443,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-sub-feature-type', 'update'), actions.savedObject.get('all-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-sub-feature-type', 'share_to_space'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_get'), actions.savedObject.get('all-licensed-sub-feature-type', 'get'), @@ -2403,6 +2455,7 @@ describe('subFeatures', () => { actions.savedObject.get('all-licensed-sub-feature-type', 'update'), actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_update'), actions.savedObject.get('all-licensed-sub-feature-type', 'delete'), + actions.savedObject.get('all-licensed-sub-feature-type', 'bulk_delete'), actions.savedObject.get('all-licensed-sub-feature-type', 'share_to_space'), actions.savedObject.get('read-sub-feature-type', 'bulk_get'), actions.savedObject.get('read-sub-feature-type', 'get'), diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts index 52702c014f0cb..bce6786f06775 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts @@ -591,6 +591,67 @@ describe('#bulkUpdate', () => { }); }); +describe('#bulkDelete', () => { + const obj1 = Object.freeze({ type: 'foo', id: 'foo-id' }); + const obj2 = Object.freeze({ type: 'bar', id: 'bar-id' }); + const namespace = 'some-ns'; + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + const objects = [obj1]; + await expectGeneralError(client.bulkDelete, { objects }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + const objects = [obj1, obj2]; + const options = { namespace }; + await expectForbiddenError(client.bulkDelete, { objects, options }); + }); + + test(`returns result of baseClient.bulkDelete when authorized`, async () => { + const apiCallReturnValue = { + statuses: [obj1, obj2].map((obj) => { + return { ...obj, success: true }; + }), + }; + clientOpts.baseClient.bulkDelete.mockReturnValue(apiCallReturnValue as any); + + const objects = [obj1, obj2]; + const options = { namespace }; + const result = await expectSuccess(client.bulkDelete, { objects, options }); + expect(result).toEqual(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + const objects = [obj1, obj2]; + const options = { namespace }; + await expectPrivilegeCheck(client.bulkDelete, { objects, options }, namespace); + }); + + test(`adds audit event when successful`, async () => { + const apiCallReturnValue = { + statuses: [obj1, obj2].map((obj) => { + return { ...obj, success: true }; + }), + }; + clientOpts.baseClient.bulkDelete.mockReturnValue(apiCallReturnValue as any); + + const objects = [obj1, obj2]; + const options = { namespace }; + await expectSuccess(client.bulkDelete, { objects, options }); + expect(clientOpts.auditLogger.log).toHaveBeenCalledTimes(2); + expectAuditEvent('saved_object_delete', 'success', { type: obj1.type, id: obj1.id }); + expectAuditEvent('saved_object_delete', 'success', { type: obj2.type, id: obj2.id }); + }); + + test(`adds audit event when not successful`, async () => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue(new Error()); + await expect(() => client.bulkDelete([obj1, obj2], { namespace })).rejects.toThrow(); + expect(clientOpts.auditLogger.log).toHaveBeenCalledTimes(2); + expectAuditEvent('saved_object_delete', 'failure', { type: obj1.type, id: obj1.id }); + expectAuditEvent('saved_object_delete', 'failure', { type: obj2.type, id: obj2.id }); + }); +}); + describe('#checkConflicts', () => { const obj1 = Object.freeze({ type: 'foo', id: 'foo-id' }); const obj2 = Object.freeze({ type: 'bar', id: 'bar-id' }); diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts index db0645992b2f7..b8e253b7f3160 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts @@ -9,6 +9,9 @@ import type { SavedObjectReferenceWithContext, SavedObjectsBaseOptions, SavedObjectsBulkCreateObject, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, + SavedObjectsBulkDeleteResponse, SavedObjectsBulkGetObject, SavedObjectsBulkResolveObject, SavedObjectsBulkUpdateObject, @@ -224,6 +227,48 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra return await this.baseClient.delete(type, id, options); } + public async bulkDelete( + objects: SavedObjectsBulkDeleteObject[], + options: SavedObjectsBulkDeleteOptions + ): Promise { + try { + const args = { objects, options }; + await this.legacyEnsureAuthorized( + this.getUniqueObjectTypes(objects), + 'bulk_delete', + options?.namespace, + { + args, + } + ); + } catch (error) { + objects.forEach(({ type, id }) => + this.auditLogger.log( + savedObjectEvent({ + action: SavedObjectAction.DELETE, + savedObject: { type, id }, + error, + }) + ) + ); + throw error; + } + const response = await this.baseClient.bulkDelete(objects, options); + response?.statuses.forEach(({ id, type, success, error }) => { + const auditEventOutcome = success === true ? 'success' : 'failure'; + const auditEventOutcomeError = error ? (error as unknown as Error) : undefined; + this.auditLogger.log( + savedObjectEvent({ + action: SavedObjectAction.DELETE, + savedObject: { type, id }, + outcome: auditEventOutcome, + error: auditEventOutcomeError, + }) + ); + }); + return response; + } + public async find(options: SavedObjectsFindOptions) { if ( this.getSpacesService() == null && diff --git a/x-pack/plugins/security_solution/common/endpoint/exceptions/exceptionable_endpoint_event_fields.ts b/x-pack/plugins/security_solution/common/endpoint/exceptions/exceptionable_endpoint_event_fields.ts index 38cbee8d70d8f..2c7b9d332072f 100644 --- a/x-pack/plugins/security_solution/common/endpoint/exceptions/exceptionable_endpoint_event_fields.ts +++ b/x-pack/plugins/security_solution/common/endpoint/exceptions/exceptionable_endpoint_event_fields.ts @@ -205,6 +205,7 @@ export const EXCEPTIONABLE_ENDPOINT_EVENT_FIELDS = [ 'process.command_line.caseless', 'process.command_line.text', 'process.entity_id', + 'process.entry_leader.interactive', 'process.executable', 'process.executable.caseless', 'process.executable.text', diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts b/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts index c397d70c6b019..15c89c8cd9c28 100644 --- a/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts +++ b/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts @@ -24,10 +24,12 @@ export const validateTree = { descendants: schema.number({ defaultValue: 1000, min: 0, max: 10000 }), // if the ancestry array isn't specified allowing 200 might be too high ancestors: schema.number({ defaultValue: 200, min: 0, max: 10000 }), - timeRange: schema.object({ - from: schema.string(), - to: schema.string(), - }), + timeRange: schema.maybe( + schema.object({ + from: schema.string(), + to: schema.string(), + }) + ), schema: schema.object({ // the ancestry field is optional ancestry: schema.maybe(schema.string({ minLength: 1 })), diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/enrichments.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/enrichments.cy.ts index ff1c4f6acb177..ca5951e2456c1 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/enrichments.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/enrichments.cy.ts @@ -30,7 +30,7 @@ import { login, visit } from '../../tasks/login'; import { ALERTS_URL } from '../../urls/navigation'; -describe('Enrichment', () => { +describe.skip('Enrichment', () => { before(() => { cleanKibana(); esArchiverLoad('risky_users'); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/resolver.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/resolver.cy.ts new file mode 100644 index 0000000000000..aa2263b9b518c --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/resolver.cy.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 { ANALYZER_NODE } from '../../screens/alerts'; + +import { openAnalyzerForFirstAlertInTimeline } from '../../tasks/alerts'; +import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; +import { getNewRule } from '../../objects/rule'; +import { cleanKibana } from '../../tasks/common'; +import { setStartDate } from '../../tasks/date_picker'; +import { TOASTER } from '../../screens/alerts_detection_rules'; +import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; +import { login, visit } from '../../tasks/login'; +import { ALERTS_URL } from '../../urls/navigation'; + +describe('Analyze events view for alerts', () => { + before(() => { + cleanKibana(); + login(); + createCustomRuleEnabled(getNewRule()); + }); + beforeEach(() => { + visit(ALERTS_URL); + waitForAlertsToPopulate(); + }); + + it('should render analyzer when button is clicked', () => { + openAnalyzerForFirstAlertInTimeline(); + cy.get(ANALYZER_NODE).first().should('be.visible'); + }); + + it(`should render an analyzer view and display + a toast indicating the date range of found events when a time range has 0 events in it`, () => { + const dateContainingZeroEvents = 'Jul 27, 2022 @ 00:00:00.000'; + setStartDate(dateContainingZeroEvents); + waitForAlertsToPopulate(); + openAnalyzerForFirstAlertInTimeline(); + cy.get(TOASTER).should('be.visible'); + cy.get(ANALYZER_NODE).first().should('be.visible'); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 28ccdef683971..db8596074ca99 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -81,6 +81,10 @@ export const SELECT_TABLE = '[data-test-subj="table"]'; export const SEND_ALERT_TO_TIMELINE_BTN = '[data-test-subj="send-alert-to-timeline-button"]'; +export const OPEN_ANALYZER_BTN = '[data-test-subj="view-in-analyzer"]'; + +export const ANALYZER_NODE = '[data-test-subj="resolver:node"'; + export const SEVERITY = '[data-test-subj^=formatted-field][data-test-subj$=severity]'; export const SOURCE_IP = '[data-test-subj^=formatted-field][data-test-subj$=source\\.ip]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index 69a0159f7f44d..b9191075a214f 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -25,6 +25,7 @@ import { TAKE_ACTION_POPOVER_BTN, TIMELINE_CONTEXT_MENU_BTN, CLOSE_FLYOUT, + OPEN_ANALYZER_BTN, } from '../screens/alerts'; import { REFRESH_BUTTON } from '../screens/security_header'; import { @@ -158,6 +159,10 @@ export const investigateFirstAlertInTimeline = () => { cy.get(SEND_ALERT_TO_TIMELINE_BTN).first().click({ force: true }); }; +export const openAnalyzerForFirstAlertInTimeline = () => { + cy.get(OPEN_ANALYZER_BTN).first().click({ force: true }); +}; + export const addAlertPropertyToTimeline = (propertySelector: string, rowIndex: number) => { cy.get(propertySelector).eq(rowIndex).trigger('mouseover'); cy.get(ALERT_TABLE_CELL_ACTIONS_ADD_TO_TIMELINE).first().click({ force: true }); diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/alert_count_by_rule_by_status.test.tsx b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/alert_count_by_rule_by_status.test.tsx new file mode 100644 index 0000000000000..df001ccf70ca9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/alert_count_by_rule_by_status.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; 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 { TestProviders } from '../../mock'; +import { AlertCountByRuleByStatus } from './alert_count_by_rule_by_status'; +import { COLUMN_HEADER_COUNT, COLUMN_HEADER_RULE_NAME } from './translations'; +import type { UseAlertCountByRuleByStatus } from './use_alert_count_by_rule_by_status'; + +type UseAlertCountByRuleByStatusReturn = ReturnType; +const defaultUseAlertCountByRuleByStatusReturn: UseAlertCountByRuleByStatusReturn = { + items: [], + isLoading: false, + updatedAt: Date.now(), +}; + +const mockUseAlertCountByRuleByStatus = jest.fn(() => defaultUseAlertCountByRuleByStatusReturn); +const mockUseAlertCountByRuleByStatusReturn = ( + overrides: Partial +) => { + mockUseAlertCountByRuleByStatus.mockReturnValue({ + ...defaultUseAlertCountByRuleByStatusReturn, + ...overrides, + }); +}; + +jest.mock('./use_alert_count_by_rule_by_status', () => ({ + useAlertCountByRuleByStatus: () => mockUseAlertCountByRuleByStatus(), +})); + +const renderComponent = () => + render( + + + + ); + +describe('AlertCountByRuleByStatus', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render empty table', () => { + const { getByText, queryByTestId } = renderComponent(); + + expect(queryByTestId('alertCountByRulePanel')).toBeInTheDocument(); + expect(getByText('No alerts to display')).toBeInTheDocument(); + }); + + it('should render a loading table', () => { + mockUseAlertCountByRuleByStatusReturn({ isLoading: true }); + const { getByText, queryByTestId } = renderComponent(); + + expect(getByText('Updating...')).toBeInTheDocument(); + expect(queryByTestId('alertCountByRuleTable')).toHaveClass('euiBasicTable-loading'); + }); + + it('should render the table columns', () => { + const { getAllByRole } = renderComponent(); + const columnHeaders = getAllByRole('columnheader'); + + expect(columnHeaders.at(0)).toHaveTextContent(COLUMN_HEADER_RULE_NAME); + expect(columnHeaders.at(1)).toHaveTextContent(COLUMN_HEADER_COUNT); + }); + + it('should render the table items', () => { + mockUseAlertCountByRuleByStatusReturn({ items: mockItem }); + const { queryByTestId } = renderComponent(); + + expect(queryByTestId(COLUMN_HEADER_RULE_NAME)).toHaveTextContent('Test Name'); + expect(queryByTestId(COLUMN_HEADER_COUNT)).toHaveTextContent('100'); + }); +}); + +const mockItem = [ + { + count: 100, + ruleName: 'Test Name', + uuid: 'uuid', + }, +]; diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/alert_count_by_rule_by_status.tsx b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/alert_count_by_rule_by_status.tsx new file mode 100644 index 0000000000000..2da871fdab83f --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/alert_count_by_rule_by_status.tsx @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; + +import type { EuiBasicTableColumn } from '@elastic/eui'; +import { EuiBasicTable, EuiEmptyPrompt, EuiLink, EuiPanel, EuiToolTip } from '@elastic/eui'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; + +import type { Status } from '../../../../common/detection_engine/schemas/common'; +import { SecurityPageName } from '../../../../common/constants'; +import { useNavigateToTimeline } from '../../../overview/components/detection_response/hooks/use_navigate_to_timeline'; +import { useQueryToggle } from '../../containers/query_toggle'; +import { FormattedCount } from '../formatted_number'; +import { HeaderSection } from '../header_section'; +import { HoverVisibilityContainer } from '../hover_visibility_container'; +import { BUTTON_CLASS as INSPECT_BUTTON_CLASS } from '../inspect'; +import { LastUpdatedAt } from '../last_updated_at'; +import { SecuritySolutionLinkAnchor } from '../links'; +import { useLocalStorage } from '../local_storage'; +import { MultiSelectPopover } from './components'; +import * as i18n from './translations'; +import type { AlertCountByRuleByStatusItem } from './use_alert_count_by_rule_by_status'; +import { useAlertCountByRuleByStatus } from './use_alert_count_by_rule_by_status'; + +interface EntityFilter { + field: string; + value: string; +} +interface AlertCountByStatusProps { + entityFilter: EntityFilter; + signalIndexName: string | null; +} + +interface StatusSelection { + [fieldName: string]: Status[]; +} + +type GetTableColumns = ( + openRuleInTimelineWithAdditionalFields: (ruleName: string) => void +) => Array>; + +const KIBANA_RULE_ALERT_FIELD = 'kibana.alert.rule.name'; +const STATUSES = ['open', 'acknowledged', 'closed'] as const; +const ALERT_COUNT_BY_RULE_BY_STATUS = 'alerts-by-status-by-rule'; +const LOCAL_STORAGE_KEY = 'alertCountByFieldNameWidgetSettings'; + +const StyledEuiPanel = euiStyled(EuiPanel)` + display: flex; + flex-direction: column; + position: relative; + overflow: hidden; + max-height: 308px; +`; + +export const AlertCountByRuleByStatus = React.memo( + ({ entityFilter, signalIndexName }: AlertCountByStatusProps) => { + const { field, value } = entityFilter; + + const queryId = `${ALERT_COUNT_BY_RULE_BY_STATUS}-by-${field}`; + const { toggleStatus, setToggleStatus } = useQueryToggle(queryId); + + const { openEntityInTimeline } = useNavigateToTimeline(); + + const columns = useMemo( + () => + getTableColumns((ruleName: string) => + openEntityInTimeline([{ field: KIBANA_RULE_ALERT_FIELD, value: ruleName }, entityFilter]) + ), + [entityFilter, openEntityInTimeline] + ); + + const [selectedStatusesByField, setSelectedStatusesByField] = useLocalStorage({ + defaultValue: { + [field]: ['open'], + }, + key: LOCAL_STORAGE_KEY, + isInvalidDefault: (valueFromStorage) => { + return !valueFromStorage; + }, + }); + + const updateSelection = useCallback( + (selection: Status[]) => { + setSelectedStatusesByField({ + ...selectedStatusesByField, + [field]: selection, + }); + }, + [field, selectedStatusesByField, setSelectedStatusesByField] + ); + + const { items, isLoading, updatedAt } = useAlertCountByRuleByStatus({ + field, + value, + queryId, + statuses: selectedStatusesByField[field] as Status[], + skip: !toggleStatus, + signalIndexName, + }); + + return ( + + + <> + } + > + + updateSelection(selectedItems as Status[]) + } + /> + + + {toggleStatus && ( + <> + {i18n.NO_ALERTS_FOUND}} titleSize="xs" /> + } + /> + + )} + + + + ); + } +); + +AlertCountByRuleByStatus.displayName = 'AlertCountByStatus'; + +export const getTableColumns: GetTableColumns = (openRuleInTimelineWithAdditionalFields) => [ + { + field: 'ruleName', + name: i18n.COLUMN_HEADER_RULE_NAME, + 'data-test-subj': i18n.COLUMN_HEADER_RULE_NAME, + align: 'left', + width: '67%', + sortable: false, + render: (ruleName: string, { uuid }) => ( + + + {ruleName} + + + ), + }, + { + field: 'count', + name: i18n.COLUMN_HEADER_COUNT, + width: '33%', + 'data-test-subj': i18n.COLUMN_HEADER_COUNT, + sortable: true, + align: 'right', + render: (count: number, { ruleName }) => ( + openRuleInTimelineWithAdditionalFields(ruleName)} + > + + + ), + }, +]; diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/index.ts b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/index.ts new file mode 100644 index 0000000000000..5897499d5b6ee --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { MultiSelectPopover } from './multiselect_popover/multiselect_popover'; diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/multiselect_popover/multiselect_popover.test.tsx b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/multiselect_popover/multiselect_popover.test.tsx new file mode 100644 index 0000000000000..019b8080a9ed3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/multiselect_popover/multiselect_popover.test.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { fireEvent, render } from '@testing-library/react'; + +import type { MultiSelectPopoverProps } from './multiselect_popover'; +import { MultiSelectPopover } from './multiselect_popover'; + +const mockSelectedItemsChange = jest.fn(); + +const defaultProps = { + title: 'title', + allItems: ['a', 'b', 'c'], + selectedItems: [], + onSelectedItemsChange: mockSelectedItemsChange, +}; + +const renderComponent = (overrides?: Partial) => + render(); + +describe('MultiSelectPopOver', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders all items', () => { + const { getByText, getByTestId } = renderComponent(); + fireEvent.click(getByTestId('multiselect-popover-button')); + + expect(getByText('title')).toBeInTheDocument(); + expect(getByText('a')).toBeInTheDocument(); + expect(getByText('b')).toBeInTheDocument(); + expect(getByText('c')).toBeInTheDocument(); + }); + + it('calls onSelectedItemdChange when item is clicked', () => { + const { getByText, getByTestId } = renderComponent(); + + fireEvent.click(getByTestId('multiselect-popover-button')); + fireEvent.click(getByText('a')); + + expect(mockSelectedItemsChange).toHaveBeenCalledWith(['a']); + }); + + it('shows selected items as selected', () => { + const { getByText, getByTestId } = renderComponent({ selectedItems: ['a'] }); + fireEvent.click(getByTestId('multiselect-popover-button')); + + // confirm there is a 'check mark' next to the selected item + expect(getByText('a').parentElement?.firstChild?.firstChild).toHaveAttribute( + 'data-euiicon-type', + 'check' + ); + expect(getByText('1')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/multiselect_popover/multiselect_popover.tsx b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/multiselect_popover/multiselect_popover.tsx new file mode 100644 index 0000000000000..ad6d9fa9961b2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/components/multiselect_popover/multiselect_popover.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, useState } from 'react'; + +import { EuiFilterButton, EuiFilterGroup, EuiFilterSelectItem, EuiPopover } from '@elastic/eui'; +export interface MultiSelectPopoverProps { + title: string; + allItems: readonly string[]; + selectedItems: string[]; + onSelectedItemsChange: (newItems: string[]) => void; +} + +export const MultiSelectPopover = React.memo( + ({ allItems, selectedItems, title, onSelectedItemsChange }: MultiSelectPopoverProps) => { + const [isItemPopoverOpen, setIsItemPopoverOpen] = useState(false); + + const onChange = useCallback( + (item: string) => onSelectedItemsChange(getUpdatedSelectedItems(item, selectedItems)), + [selectedItems, onSelectedItemsChange] + ); + + const itemList = useMemo(() => { + return allItems.map((item, index) => ( + onChange(item)} + title={item} + > + {item} + + )); + }, [allItems, selectedItems, onChange]); + + const togglePopover = useCallback( + (toState?: boolean) => { + setIsItemPopoverOpen((s) => (toState ? toState : !s)); + }, + [setIsItemPopoverOpen] + ); + + return ( + + togglePopover()} + numFilters={allItems.length} + isSelected={isItemPopoverOpen} + hasActiveFilters={selectedItems.length > 0} + numActiveFilters={selectedItems.length} + > + {title} + + + } + isOpen={isItemPopoverOpen} + closePopover={() => togglePopover(false)} + panelPaddingSize="none" + > + {itemList} + + ); + } +); + +MultiSelectPopover.displayName = 'MultiSelectPopover'; + +const getUpdatedSelectedItems = (item: string, selectedItems: string[]): string[] => { + const selectedGroupIndex = selectedItems.indexOf(item); + const updatedSelectedItems = [...selectedItems]; + if (selectedGroupIndex >= 0) { + updatedSelectedItems.splice(selectedGroupIndex, 1); + } else { + updatedSelectedItems.push(item); + } + return updatedSelectedItems; +}; diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/index.ts b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/index.ts new file mode 100644 index 0000000000000..ef21c6282e0ba --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { AlertCountByRuleByStatus } from './alert_count_by_rule_by_status'; diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/mock_data.ts b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/mock_data.ts new file mode 100644 index 0000000000000..85cd90cc5226e --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/mock_data.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ALERTS_QUERY_NAMES } from '../../../detections/containers/detection_engine/alerts/constants'; +import { buildRuleAlertsByEntityQuery } from './use_alert_count_by_rule_by_status'; + +export const mockAlertCountByRuleResult = { + aggregations: { + alertsByRuleAggregation: { + buckets: [ + { + key: 'Critical', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '100', + }, + }, + ], + }, + }, + }, + { + key: 'High', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '200', + }, + }, + ], + }, + }, + }, + { + key: 'Medium', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '300', + }, + }, + ], + }, + }, + }, + { + key: 'another rule', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '400', + }, + }, + ], + }, + }, + }, + { + key: 'bad users!!', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '500', + }, + }, + ], + }, + }, + }, + { + key: 'endpoint', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '600', + }, + }, + ], + }, + }, + }, + { + key: 'low', + doc_count: 1, + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': '700', + }, + }, + ], + }, + }, + }, + ], + }, + }, +}; + +export const parsedAlertCountByRuleResult = [ + { + ruleName: 'Critical', + count: 1, + uuid: '100', + }, + { + ruleName: 'High', + count: 1, + uuid: '200', + }, + { + ruleName: 'Medium', + count: 1, + uuid: '300', + }, + { + ruleName: 'another rule', + count: 1, + uuid: '400', + }, + { + ruleName: 'bad users!!', + count: 1, + uuid: '500', + }, + { + ruleName: 'endpoint', + count: 1, + uuid: '600', + }, + { + ruleName: 'low', + count: 1, + uuid: '700', + }, +]; + +export const mockQuery = () => ({ + query: buildRuleAlertsByEntityQuery({ + from: '2020-07-07T08:20:18.966Z', + to: '2020-07-08T08:20:18.966Z', + statuses: ['open'], + field: 'test_field', + value: 'test_value', + }), + indexName: 'signalIndexName', + skip: false, + queryName: ALERTS_QUERY_NAMES.ALERTS_COUNT_BY_STATUS, +}); diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/translations.ts b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/translations.ts new file mode 100644 index 0000000000000..e95673993353e --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/translations.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const Status = i18n.translate('xpack.securitySolution.alertCountByRuleByStatus.status', { + defaultMessage: 'Status', +}); + +export const ALERTS_BY_RULE = i18n.translate( + 'xpack.securitySolution.alertCountByRuleByStatus.alertsByRule', + { + defaultMessage: 'Alerts by Rule', + } +); +export const COLUMN_HEADER_RULE_NAME = i18n.translate( + 'xpack.securitySolution.alertCountByRuleByStatus.ruleName', + { + defaultMessage: 'kibana.alert.rule.name', + } +); + +export const COLUMN_HEADER_COUNT = i18n.translate( + 'xpack.securitySolution.alertCountByRuleByStatus.count', + { + defaultMessage: 'count', + } +); + +export const TOOLTIP_TITLE = i18n.translate( + 'xpack.securitySolution.alertCountByRuleByStatus.tooltipTitle', + { + defaultMessage: 'Rule name', + } +); + +export const NO_ALERTS_FOUND = i18n.translate( + 'xpack.securitySolution.alertCountByRuleByStatus.noRuleAlerts', + { + defaultMessage: 'No alerts to display', + } +); diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/use_alert_count_by_rule_by_status.test.ts b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/use_alert_count_by_rule_by_status.test.ts new file mode 100644 index 0000000000000..4caf3bf6c04db --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/use_alert_count_by_rule_by_status.test.ts @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { renderHook } from '@testing-library/react-hooks'; + +import { mockQuery, mockAlertCountByRuleResult, parsedAlertCountByRuleResult } from './mock_data'; +import type { + UseAlertCountByRuleByStatus, + UseAlertCountByRuleByStatusProps, +} from './use_alert_count_by_rule_by_status'; +import { useAlertCountByRuleByStatus } from './use_alert_count_by_rule_by_status'; + +const dateNow = new Date('2022-04-15T12:00:00.000Z').valueOf(); +const mockDateNow = jest.fn().mockReturnValue(dateNow); +Date.now = jest.fn(() => mockDateNow()) as unknown as DateConstructor['now']; + +const defaultUseQueryAlertsReturn = { + loading: false, + data: null, + setQuery: () => {}, + response: '', + request: '', + refetch: () => {}, +}; + +const mockUseQueryAlerts = jest.fn().mockReturnValue(defaultUseQueryAlertsReturn); +jest.mock('../../../detections/containers/detection_engine/alerts/use_query', () => { + return { + useQueryAlerts: (...props: unknown[]) => mockUseQueryAlerts(...props), + }; +}); + +const from = '2020-07-07T08:20:18.966Z'; +const to = '2020-07-08T08:20:18.966Z'; + +const mockUseGlobalTime = jest + .fn() + .mockReturnValue({ from, to, setQuery: jest.fn(), deleteQuery: jest.fn() }); +jest.mock('../../containers/use_global_time', () => { + return { + useGlobalTime: (...props: unknown[]) => mockUseGlobalTime(...props), + }; +}); + +jest.mock('../../../detections/containers/detection_engine/alerts/use_signal_index', () => ({ + useSignalIndex: () => ({ signalIndexName: 'signalIndexName' }), +})); + +const renderUseAlertCountByRuleByStatus = ( + overrides: Partial = {} +) => + renderHook>(() => + useAlertCountByRuleByStatus({ + skip: false, + field: 'test_field', + value: 'test_value', + statuses: ['open'], + queryId: 'queryId', + signalIndexName: 'signalIndexName', + ...overrides, + }) + ); + +describe('useAlertCountByRuleByStatus', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockDateNow.mockReturnValue(dateNow); + mockUseQueryAlerts.mockReturnValue(defaultUseQueryAlertsReturn); + }); + + it('should return default values', () => { + const { result } = renderUseAlertCountByRuleByStatus(); + + expect(result.current).toEqual({ + items: [], + isLoading: false, + updatedAt: dateNow, + }); + + expect(mockUseQueryAlerts).toBeCalledWith(mockQuery()); + }); + + it('should return parsed items', () => { + mockUseQueryAlerts.mockReturnValue({ + ...defaultUseQueryAlertsReturn, + data: mockAlertCountByRuleResult, + }); + + const { result } = renderUseAlertCountByRuleByStatus(); + + expect(result.current).toEqual({ + items: parsedAlertCountByRuleResult, + isLoading: false, + updatedAt: dateNow, + }); + }); + + it('should return new updatedAt', () => { + const newDateNow = new Date('2022-04-08T14:00:00.000Z').valueOf(); + mockDateNow.mockReturnValue(newDateNow); + mockDateNow.mockReturnValueOnce(dateNow); + mockUseQueryAlerts.mockReturnValue({ + ...defaultUseQueryAlertsReturn, + data: mockAlertCountByRuleResult, + }); + + const { result } = renderUseAlertCountByRuleByStatus(); + expect(mockDateNow).toHaveBeenCalled(); + expect(result.current).toEqual({ + items: parsedAlertCountByRuleResult, + isLoading: false, + updatedAt: newDateNow, + }); + }); + + it('should skip the query', () => { + const { result } = renderUseAlertCountByRuleByStatus({ skip: true }); + + expect(mockUseQueryAlerts).toBeCalledWith({ ...mockQuery(), skip: true }); + + expect(result.current).toEqual({ + items: [], + isLoading: false, + updatedAt: dateNow, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/use_alert_count_by_rule_by_status.ts b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/use_alert_count_by_rule_by_status.ts new file mode 100644 index 0000000000000..b59862bf0d6ee --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/alert_count_by_status/use_alert_count_by_rule_by_status.ts @@ -0,0 +1,202 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, useEffect, useState } from 'react'; + +import type { Status } from '../../../../common/detection_engine/schemas/common'; +import type { GenericBuckets } from '../../../../common/search_strategy'; +import { ALERTS_QUERY_NAMES } from '../../../detections/containers/detection_engine/alerts/constants'; +import { useQueryAlerts } from '../../../detections/containers/detection_engine/alerts/use_query'; +import { useGlobalTime } from '../../containers/use_global_time'; +import { useQueryInspector } from '../page/manage_query'; + +export interface AlertCountByRuleByStatusItem { + ruleName: string; + count: number; + uuid: string; +} + +export interface UseAlertCountByRuleByStatusProps { + field: string; + value: string; + queryId: string; + statuses: Status[]; + skip?: boolean; + signalIndexName: string | null; +} +export type UseAlertCountByRuleByStatus = (props: UseAlertCountByRuleByStatusProps) => { + items: AlertCountByRuleByStatusItem[]; + isLoading: boolean; + updatedAt: number; +}; + +const ALERTS_BY_RULE_AGG = 'alertsByRuleAggregation'; + +export const useAlertCountByRuleByStatus: UseAlertCountByRuleByStatus = ({ + field, + value, + queryId, + statuses, + skip = false, + signalIndexName, +}) => { + const [updatedAt, setUpdatedAt] = useState(Date.now()); + const [items, setItems] = useState([]); + + const { to, from, deleteQuery, setQuery } = useGlobalTime(); + + const { + loading: isLoading, + data, + setQuery: setAlertsQuery, + response, + request, + refetch: refetchQuery, + } = useQueryAlerts({ + query: buildRuleAlertsByEntityQuery({ + from, + to, + field, + value, + statuses, + }), + skip, + queryName: ALERTS_QUERY_NAMES.ALERTS_COUNT_BY_STATUS, + indexName: signalIndexName, + }); + + useEffect(() => { + setAlertsQuery( + buildRuleAlertsByEntityQuery({ + from, + to, + field, + value, + statuses, + }) + ); + }, [setAlertsQuery, from, to, field, value, statuses]); + + useEffect(() => { + if (!data) { + setItems([]); + } else { + setItems(parseAlertCountByRuleItems(data.aggregations as AlertCountByRuleByFieldAggregation)); + } + setUpdatedAt(Date.now()); + }, [data]); + + const refetch = useCallback(() => { + if (!skip && refetchQuery) { + refetchQuery(); + } + }, [skip, refetchQuery]); + + useQueryInspector({ + deleteQuery, + inspect: { + dsl: [request], + response: [response], + }, + refetch, + setQuery, + queryId, + loading: isLoading, + }); + + return { items, isLoading, updatedAt }; +}; + +export const buildRuleAlertsByEntityQuery = ({ + from, + to, + field, + value, + statuses, +}: { + from: string; + to: string; + statuses: string[]; + field: string; + value: string; +}) => ({ + size: 0, + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: from, + lte: to, + }, + }, + }, + { + terms: { + 'kibana.alert.workflow_status': statuses, + }, + }, + { + term: { + [field]: value, + }, + }, + ], + }, + }, + aggs: { + [ALERTS_BY_RULE_AGG]: { + terms: { + field: 'kibana.alert.rule.name', + size: 100, + }, + aggs: { + ruleUuid: { + top_hits: { + _source: ['kibana.alert.rule.uuid'], + size: 1, + }, + }, + }, + }, + }, +}); + +interface RuleUuidData extends GenericBuckets { + ruleUuid: { + hits: { + hits: [ + { + _source: { + 'kibana.alert.rule.uuid': string; + }; + } + ]; + }; + }; +} + +interface AlertCountByRuleByFieldAggregation { + [ALERTS_BY_RULE_AGG]: { + buckets: RuleUuidData[]; + }; +} + +const parseAlertCountByRuleItems = ( + aggregations?: AlertCountByRuleByFieldAggregation +): AlertCountByRuleByStatusItem[] => { + const buckets = aggregations?.[ALERTS_BY_RULE_AGG].buckets ?? []; + return buckets.map((bucket) => { + const uuid = bucket.ruleUuid.hits?.hits[0]?._source['kibana.alert.rule.uuid'] || ''; + return { + ruleName: bucket.key, + count: bucket.doc_count, + uuid, + }; + }); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx index ca30250136f45..b1819128a14a8 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiButton, EuiButtonEmpty } from '@elastic/eui'; import { useDispatch } from 'react-redux'; +import { sourcererSelectors } from '../../../store'; import { InputsModelId } from '../../../store/inputs/constants'; import { inputsActions } from '../../../store/inputs'; import { updateProviders } from '../../../../timelines/store/timeline/actions'; @@ -18,6 +19,7 @@ import type { DataProvider } from '../../../../../common/types'; import { TimelineId, TimelineType } from '../../../../../common/types/timeline'; import { useCreateTimeline } from '../../../../timelines/components/timeline/properties/use_create_timeline'; import { ACTION_INVESTIGATE_IN_TIMELINE } from '../../../../detections/components/alerts_table/translations'; +import { useDeepEqualSelector } from '../../../hooks/use_selector'; export const InvestigateInTimelineButton: React.FunctionComponent<{ asEmptyButton: boolean; @@ -25,6 +27,14 @@ export const InvestigateInTimelineButton: React.FunctionComponent<{ }> = ({ asEmptyButton, children, dataProviders, ...rest }) => { const dispatch = useDispatch(); + const getDataViewsSelector = useMemo( + () => sourcererSelectors.getSourcererDataViewsSelector(), + [] + ); + const { defaultDataView, signalIndexName } = useDeepEqualSelector((state) => + getDataViewsSelector(state) + ); + const clearTimeline = useCreateTimeline({ timelineId: TimelineId.active, timelineType: TimelineType.default, @@ -46,14 +56,14 @@ export const InvestigateInTimelineButton: React.FunctionComponent<{ dispatch( sourcererActions.setSelectedDataView({ id: SourcererScopeName.timeline, - selectedDataViewId: 'security-solution-default', - selectedPatterns: ['.alerts-security.alerts-default'], + selectedDataViewId: defaultDataView.id, + selectedPatterns: [signalIndexName || ''], }) ); // Unlock the time range from the global time range dispatch(inputsActions.removeLinkTo([InputsModelId.timeline, InputsModelId.global])); } - }, [dispatch, clearTimeline, dataProviders]); + }, [dataProviders, clearTimeline, dispatch, defaultDataView.id, signalIndexName]); return asEmptyButton ? ( { + it('Should show "updating" text while loading', () => { + const { getByText } = render(); + + expect(getByText('Updating...')).toBeInTheDocument(); + expect(() => getByText(/Updated/)).toThrow(); + }); + + it('should render "updated" text when loaded', () => { + const { getByText } = render( + + + + ); + + expect(getByText(/Updated/)).toBeInTheDocument(); + expect(() => getByText('Updating...')).toThrow(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/last_updated_at/last_updated_at.tsx b/x-pack/plugins/security_solution/public/common/components/last_updated_at/last_updated_at.tsx new file mode 100644 index 0000000000000..a596d3f0b2a3b --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/last_updated_at/last_updated_at.tsx @@ -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 React from 'react'; + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedRelative } from '@kbn/i18n-react'; + +interface LastUpdatedAtProps { + updatedAt: number; + isUpdating: boolean; +} + +const UPDATING = i18n.translate('xpack.securitySolution.detectionResponse.updating', { + defaultMessage: 'Updating...', +}); + +const UPDATED = i18n.translate('xpack.securitySolution.detectionResponse.updated', { + defaultMessage: 'Updated', +}); + +export const LastUpdatedAt: React.FC = ({ isUpdating, updatedAt }) => ( + + {isUpdating ? ( + {UPDATING} + ) : ( + + <>{UPDATED} + + + )} + +); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/constants.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/constants.ts index 5bd4206761219..a6dcf82dd4071 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/constants.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/constants.ts @@ -9,7 +9,9 @@ import { APP_UI_ID } from '../../../../../common/constants'; export const ALERTS_QUERY_NAMES = { ADD_EXCEPTION_FLYOUT: `${APP_UI_ID} fetchAlerts addExceptionFlyout`, + ALERTS_COUNT_BY_STATUS: `${APP_UI_ID} fetchAlerts byRulebyCount`, BY_ID: `${APP_UI_ID} fetchAlerts byId`, + BY_RULE_BY_STATUS: `${APP_UI_ID} fetchAlerts byRulebyStatus`, BY_RULE_ID: `${APP_UI_ID} fetchAlerts byRuleId`, BY_SEVERITY: `${APP_UI_ID} fetchAlerts bySeverity`, BY_STATUS: `${APP_UI_ID} fetchAlerts byStatus`, @@ -17,8 +19,8 @@ export const ALERTS_QUERY_NAMES = { COUNT: `${APP_UI_ID} fetchAlerts count`, HISTOGRAM: `${APP_UI_ID} fetchAlerts histogram`, PREVALENCE: `${APP_UI_ID} fetchAlerts prevalence`, + SOC_TRENDS: `${APP_UI_ID} fetchAlerts socTrends`, TREE_MAP: `${APP_UI_ID} fetchAlerts treeMap`, VULNERABLE_HOSTS: `${APP_UI_ID} fetchAlerts vulnerableHosts`, VULNERABLE_USERS: `${APP_UI_ID} fetchAlerts vulnerableUsers`, - SOC_TRENDS: `${APP_UI_ID} fetchAlerts socTrends`, } as const; diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx index 7bac79b20a821..fb39b402c84d2 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx @@ -5,18 +5,27 @@ * 2.0. */ -import { EuiHorizontalRule, EuiSpacer, EuiWindowEvent } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiSpacer, + EuiWindowEvent, +} from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { useEffect, useCallback, useMemo } from 'react'; import { useDispatch } from 'react-redux'; import type { Filter } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; + +import { AlertsByStatus } from '../../../overview/components/detection_response/alerts_by_status'; +import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index'; +import { useAlertsPrivileges } from '../../../detections/containers/detection_engine/alerts/use_alerts_privileges'; import { InputsModelId } from '../../../common/store/inputs/constants'; import type { HostItem } from '../../../../common/search_strategy'; import { LastEventIndexKey } from '../../../../common/search_strategy'; import { SecurityPageName } from '../../../app/types'; -import type { UpdateDateRange } from '../../../common/components/charts/common'; import { FiltersGlobal } from '../../../common/components/filters_global'; import { HeaderPage } from '../../../common/components/header_page'; import { LastEventTime } from '../../../common/components/last_event_time'; @@ -26,7 +35,6 @@ import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml import { useMlCapabilities } from '../../../common/components/ml/hooks/use_ml_capabilities'; import { scoreIntervalToDateTime } from '../../../common/components/ml/score/score_interval_to_datetime'; import { SecuritySolutionTabNavigation } from '../../../common/components/navigation'; -import { HostsDetailsKpiComponent } from '../../components/kpi_hosts'; import { HostOverview } from '../../../overview/components/host_overview'; import { SiemSearchBar } from '../../../common/components/search_bar'; import { SecuritySolutionPageWrapper } from '../../../common/components/page_wrapper'; @@ -55,8 +63,10 @@ import { manageQuery } from '../../../common/components/page/manage_query'; import { useInvalidFilterQuery } from '../../../common/hooks/use_invalid_filter_query'; import { useSourcererDataView } from '../../../common/containers/sourcerer'; import { LandingPageComponent } from '../../../common/components/landing_page'; +import { AlertCountByRuleByStatus } from '../../../common/components/alert_count_by_status'; import { useLicense } from '../../../common/hooks/use_license'; +const ES_HOST_FIELD = 'host.hostname'; const HostOverviewManage = manageQuery(HostOverview); const HostDetailsComponent: React.FC = ({ detailName, hostDetailsPagePath }) => { @@ -75,6 +85,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); const { globalFullScreen } = useGlobalFullScreen(); + const { signalIndexName } = useSignalIndex(); const capabilities = useMlCapabilities(); const kibana = useKibana(); @@ -86,22 +97,6 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta const isEnterprisePlus = useLicense().isEnterprise(); - const updateDateRange = useCallback( - ({ x }) => { - if (!x) { - return; - } - const [min, max] = x; - dispatch( - setAbsoluteRangeDatePicker({ - id: InputsModelId.global, - from: new Date(min).toISOString(), - to: new Date(max).toISOString(), - }) - ); - }, - [dispatch] - ); const narrowDateRange = useCallback( (score, interval) => { const fromTo = scoreIntervalToDateTime(score, interval); @@ -139,6 +134,17 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta const isPlatinumOrTrialLicense = useMlCapabilities().isPlatinumOrTrialLicense; + const { hasKibanaREAD, hasIndexRead } = useAlertsPrivileges(); + const canReadAlerts = hasKibanaREAD && hasIndexRead; + + const entityFilter = useMemo( + () => ({ + field: ES_HOST_FIELD, + value: detailName, + }), + [detailName] + ); + return ( <> {indicesExist ? ( @@ -190,21 +196,29 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta /> )} - - - - + {canReadAlerts && ( + <> + + + + + + + + + + + )} + { expect(getRightOfCursorText()).toEqual('ate'); }); + it('should select all text when ctrl or cmd + a is pressed', () => { + typeKeyboardKey('{ctrl>}a{/ctrl}'); + let selection = window.getSelection(); + expect(selection!.toString()).toEqual('isolate'); + + selection!.removeAllRanges(); + + typeKeyboardKey('{meta>}a{/meta}'); + selection = window.getSelection(); + expect(selection!.toString()).toEqual('isolate'); + }); + // FIXME:PT uncomment once task OLM task #4384 is implemented it.skip('should return original cursor position if input history is closed with no selection', async () => { typeKeyboardKey('{Enter}'); // add `isolate` to the input history diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/input_capture.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/input_capture.tsx index d6ed5a6cc243b..b4905807538f0 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/input_capture.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/components/input_capture.tsx @@ -100,7 +100,7 @@ export const InputCapture = memo( const getTestId = useTestIdGenerator(useDataTestSubj()); // Reference to the `
` that take in focus (`tabIndex`) const focusEleRef = useRef(null); - + const childrenEleRef = useRef(null); const hiddenInputEleRef = useRef(null); const getTextSelection = useCallback((): string => { @@ -130,8 +130,22 @@ export const InputCapture = memo( const handleOnKeyDown = useCallback( (ev) => { - // allows for clipboard events to be captured via onPaste event handler + // handles the ctrl + a select and allows for clipboard events to be captured via onPaste event handler if (ev.metaKey || ev.ctrlKey) { + if (ev.key === 'a') { + ev.preventDefault(); + const selection = window.getSelection(); + if (selection && childrenEleRef.current) { + const range = document.createRange(); + range.selectNodeContents(childrenEleRef.current); + if (range.toString().length > 0) { + // clear any current selection + selection.removeAllRanges(); + // add the input text selection + selection.addRange(range); + } + } + } return; } @@ -260,7 +274,9 @@ export const InputCapture = memo( `Selection` object for 'focusNode` and `anchorNode` are within the input capture area. */}
- {children} +
+ {children} +
css` - max-width: 100%; - `} + max-width: 100%; `; -export const ActionsLogEmptyState = memo(() => { - const { docLinks } = useKibana().services; +export const ActionsLogEmptyState = memo( + ({ 'data-test-subj': dataTestSubj }: { 'data-test-subj'?: string }) => { + const { docLinks } = useKibana().services; - return ( - - - {i18n.translate('xpack.securitySolution.actions_log.empty.title', { - defaultMessage: 'Actions history is empty', - })} - - } - body={ -
- {i18n.translate('xpack.securitySolution.actions_log.empty.content', { - defaultMessage: 'No response actions performed', - })} -
- } - actions={[ - - {i18n.translate('xpack.securitySolution.actions_log.empty.link', { - defaultMessage: 'Read more about response actions', - })} - , - ]} - /> -
- ); -}); + return ( + + + {i18n.translate('xpack.securitySolution.actions_log.empty.title', { + defaultMessage: 'Actions history is empty', + })} + + } + body={ +
+ {i18n.translate('xpack.securitySolution.actions_log.empty.content', { + defaultMessage: 'No response actions performed', + })} +
+ } + actions={[ + + {i18n.translate('xpack.securitySolution.actions_log.empty.link', { + defaultMessage: 'Read more about response actions', + })} + , + ]} + /> +
+ ); + } +); ActionsLogEmptyState.displayName = 'ActionsLogEmptyState'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx index 564a8f0d8e084..9fb8cce0f291a 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx @@ -16,6 +16,7 @@ import { ActionLogDateRangePicker, } from './actions_log_date_range_picker'; import { ActionsLogFilter } from './actions_log_filter'; +import { ActionsLogUsersFilter } from './actions_log_users_filter'; import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; export const ActionsLogFilters = memo( @@ -27,6 +28,7 @@ export const ActionsLogFilters = memo( onChangeHostsFilter, onChangeCommandsFilter, onChangeStatusesFilter, + onChangeUsersFilter, onRefresh, onRefreshChange, onTimeChange, @@ -38,6 +40,7 @@ export const ActionsLogFilters = memo( onChangeHostsFilter: (selectedCommands: string[]) => void; onChangeCommandsFilter: (selectedCommands: string[]) => void; onChangeStatusesFilter: (selectedStatuses: string[]) => void; + onChangeUsersFilter: (selectedUsers: string[]) => void; onRefresh: () => void; onRefreshChange: (evt: OnRefreshChangeProps) => void; onTimeChange: ({ start, end }: DurationRange) => void; @@ -79,10 +82,13 @@ export const ActionsLogFilters = memo( return ( - + + + + {filters} - + { + let render: ( + props?: React.ComponentProps + ) => ReturnType; + let renderResult: ReturnType; + let history: AppContextTestRender['history']; + let mockedContext: AppContextTestRender; + + const testPrefix = 'response-actions-list-users-filter'; + let onChangeUsersFilter: jest.Mock; + + beforeEach(async () => { + onChangeUsersFilter = jest.fn(); + mockedContext = createAppRootMockRenderer(); + ({ history } = mockedContext); + render = (props?: React.ComponentProps) => + (renderResult = mockedContext.render( + + )); + reactTestingLibrary.act(() => { + history.push(`${MANAGEMENT_PATH}/response_actions`); + }); + }); + + it('should show a search input for users', () => { + render(); + + const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + expect(searchInput).toBeTruthy(); + expect(searchInput.getAttribute('placeholder')).toEqual( + 'Filter by user or comma separated list of users' + ); + }); + + it('should search on given search string on enter', () => { + render(); + + const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + userEvent.type(searchInput, 'usernameX'); + userEvent.type(searchInput, '{enter}'); + expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX']); + }); + + it('should search comma separated strings as multiple users', () => { + render(); + + const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + userEvent.type(searchInput, 'usernameX,usernameY,usernameZ'); + userEvent.type(searchInput, '{enter}'); + expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX', 'usernameY', 'usernameZ']); + }); + + it('should ignore white spaces in a given username when updating the API params', () => { + render(); + + const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + userEvent.type(searchInput, ' usernameX '); + userEvent.type(searchInput, '{enter}'); + expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX']); + }); + + it('should ignore white spaces in comma separated usernames when updating the API params', () => { + render(); + + const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + userEvent.type(searchInput, ' , usernameX ,usernameY , '); + userEvent.type(searchInput, '{enter}'); + expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX', 'usernameY']); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.tsx new file mode 100644 index 0000000000000..d9de7986c5e80 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.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, { memo, useCallback, useState, useEffect } from 'react'; +import { EuiFieldSearch, EuiFormControlLayout } from '@elastic/eui'; +import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; +import { FILTER_NAMES } from '../translations'; +import { useActionHistoryUrlParams } from './use_action_history_url_params'; + +export const ActionsLogUsersFilter = memo( + ({ + isFlyout, + onChangeUsersFilter, + }: { + isFlyout: boolean; + onChangeUsersFilter: (selectedUserIds: string[]) => void; + }) => { + const getTestId = useTestIdGenerator('response-actions-list'); + const { users: usersFromUrlParams, setUrlUsersFilters } = useActionHistoryUrlParams(); + const [searchValue, setSearchValue] = useState(''); + + const onChange = useCallback( + (e: React.ChangeEvent) => { + setSearchValue(e.target.value); + }, + [setSearchValue] + ); + + const onSearch = useCallback(() => { + const userIds = searchValue.split(',').reduce((acc, curr) => { + if (curr.trim() !== '') { + acc.push(curr.trim()); + } + return acc; + }, []); + onChangeUsersFilter(userIds); + if (!isFlyout) { + setUrlUsersFilters(userIds.join(',')); + } + }, [isFlyout, onChangeUsersFilter, searchValue, setUrlUsersFilters]); + + const onClear = useCallback(() => { + setSearchValue(''); + onChangeUsersFilter([]); + if (!isFlyout) { + setUrlUsersFilters(''); + } + }, [isFlyout, onChangeUsersFilter, setUrlUsersFilters, setSearchValue]); + + // on load with users in urlParams, set the search value + useEffect(() => { + if (usersFromUrlParams && usersFromUrlParams.length > 0) { + setSearchValue(usersFromUrlParams.join(',')); + } + // do this only once on load + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + + + ); + } +); + +ActionsLogUsersFilter.displayName = 'ActionsLogUsersFilter'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts index 6f22b512d1bf1..5b62dbe814d3c 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts @@ -7,7 +7,7 @@ import { actionsLogFiltersFromUrlParams } from './use_action_history_url_params'; describe('#actionsLogFiltersFromUrlParams', () => { - it('should not use invalid command values to URL params', () => { + it('should not use invalid command values from URL params', () => { expect(actionsLogFiltersFromUrlParams({ commands: 'asa,was' })).toEqual({ commands: undefined, endDate: undefined, @@ -18,7 +18,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { }); }); - it('should use valid command values to URL params', () => { + it('should use valid command values from URL params', () => { expect( actionsLogFiltersFromUrlParams({ commands: 'kill-process,isolate,processes,release,suspend-process', @@ -33,7 +33,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { }); }); - it('should not use invalid status values to URL params', () => { + it('should not use invalid status values from URL params', () => { expect(actionsLogFiltersFromUrlParams({ statuses: 'asa,was' })).toEqual({ commands: undefined, endDate: undefined, @@ -44,7 +44,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { }); }); - it('should use valid status values to URL params', () => { + it('should use valid status values from URL params', () => { expect( actionsLogFiltersFromUrlParams({ statuses: 'successful,pending,failed', @@ -59,23 +59,27 @@ describe('#actionsLogFiltersFromUrlParams', () => { }); }); - it('should use valid command and status values to URL params', () => { + it('should use valid command and status along with given host, user and date values from URL params', () => { expect( actionsLogFiltersFromUrlParams({ commands: 'release,kill-process,isolate,processes,suspend-process', statuses: 'successful,pending,failed', + hosts: 'host-1,host-2', + users: 'user-1,user-2', + startDate: '2022-09-12T08:00:00.000Z', + endDate: '2022-09-12T08:30:33.140Z', }) ).toEqual({ commands: ['isolate', 'kill-process', 'processes', 'release', 'suspend-process'], - endDate: undefined, - hosts: undefined, - startDate: undefined, + endDate: '2022-09-12T08:30:33.140Z', + hosts: ['host-1', 'host-2'], + startDate: '2022-09-12T08:00:00.000Z', statuses: ['failed', 'pending', 'successful'], - users: undefined, + users: ['user-1', 'user-2'], }); }); - it('should use set given relative startDate and endDate values to URL params', () => { + it('should use given relative startDate and endDate values URL params', () => { expect( actionsLogFiltersFromUrlParams({ startDate: 'now-24h/h', @@ -91,7 +95,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { }); }); - it('should use set given absolute startDate and endDate values to URL params', () => { + it('should use given absolute startDate and endDate values URL params', () => { expect( actionsLogFiltersFromUrlParams({ startDate: '2022-09-12T08:00:00.000Z', @@ -107,7 +111,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { }); }); - it('should use set given hosts values to URL params', () => { + it('should use given hosts values from URL params', () => { expect( actionsLogFiltersFromUrlParams({ hosts: 'agent-id-1,agent-id-2', @@ -121,4 +125,19 @@ describe('#actionsLogFiltersFromUrlParams', () => { users: undefined, }); }); + + it('should use given users values from URL params', () => { + expect( + actionsLogFiltersFromUrlParams({ + users: 'usernameA,usernameB', + }) + ).toEqual({ + commands: undefined, + endDate: undefined, + hosts: undefined, + startDate: undefined, + statuses: undefined, + users: ['usernameA', 'usernameB'], + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx index e76fb65e582ce..549b03fedfbf1 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import * as reactTestingLibrary from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; +import type { IHttpFetchError } from '@kbn/core-http-browser'; import { createAppRootMockRenderer, type AppContextTestRender, @@ -23,7 +24,7 @@ import uuid from 'uuid'; let mockUseGetEndpointActionList: { isFetched?: boolean; isFetching?: boolean; - error?: null; + error?: Partial | null; data?: ActionListApiResponse; refetch: () => unknown; }; @@ -166,6 +167,28 @@ describe('Response Actions Log', () => { jest.clearAllMocks(); }); + describe('When index does not exist yet', () => { + it('should show global loader when waiting for response', () => { + mockUseGetEndpointActionList = { + ...baseMockedActionList, + isFetched: false, + isFetching: true, + }; + render(); + expect(renderResult.getByTestId(`${testPrefix}-global-loader`)).toBeTruthy(); + }); + it('should show empty page when there is no index', () => { + mockUseGetEndpointActionList = { + ...baseMockedActionList, + error: { + body: { statusCode: 404, message: 'index_not_found_exception' }, + }, + }; + render(); + expect(renderResult.getByTestId(`${testPrefix}-empty-state`)).toBeTruthy(); + }); + }); + describe('Without data', () => { it('should show date filters', () => { render(); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx index 5e674f83f4af2..d7b923dec5058 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx @@ -116,9 +116,9 @@ export const ResponseActionsLog = memo< Pick & { showHostNames?: boolean; isFlyout?: boolean; - setIsDataCallback?: (isData: boolean) => void; + setIsDataInResponse?: (isData: boolean) => void; } ->(({ agentIds, showHostNames = false, isFlyout = true, setIsDataCallback }) => { +>(({ agentIds, showHostNames = false, isFlyout = true, setIsDataInResponse }) => { const { pagination: paginationFromUrlParams, setPagination: setPaginationOnUrlParams } = useUrlPagination(); const { @@ -127,6 +127,7 @@ export const ResponseActionsLog = memo< statuses: statusesFromUrl, startDate: startDateFromUrl, endDate: endDateFromUrl, + users: usersFromUrl, } = useActionHistoryUrlParams(); const getTestId = useTestIdGenerator('response-actions-list'); @@ -134,6 +135,7 @@ export const ResponseActionsLog = memo< [k: ActionListApiResponse['data'][number]['id']]: React.ReactNode; }>({}); + // Used to decide if display global loader or not (only the fist time tha page loads) const [isFirstAttempt, setIsFirstAttempt] = useState(true); const [queryParams, setQueryParams] = useState({ @@ -157,9 +159,10 @@ export const ResponseActionsLog = memo< statuses: statusesFromUrl?.length ? (statusesFromUrl as ResponseActionStatus[]) : prevState.statuses, + userIds: usersFromUrl?.length ? usersFromUrl : prevState.userIds, })); } - }, [commandsFromUrl, agentIdsFromUrl, isFlyout, statusesFromUrl, setQueryParams]); + }, [commandsFromUrl, agentIdsFromUrl, isFlyout, statusesFromUrl, setQueryParams, usersFromUrl]); // date range picker state and handlers const { dateRangePickerState, onRefreshChange, onTimeChange } = useDateRangePicker(isFlyout); @@ -180,6 +183,26 @@ export const ResponseActionsLog = memo< { retry: false } ); + // Hide page header when there is no actions index calling the setIsDataInResponse with false value. + // Otherwise, it shows the page header calling the setIsDataInResponse with true value and it also keeps track + // if the API request was done for the first time. + useEffect(() => { + if ( + !isFetching && + error?.body?.statusCode === 404 && + error?.body?.message === 'index_not_found_exception' + ) { + if (setIsDataInResponse) { + setIsDataInResponse(false); + } + } else if (!isFetching && actionList) { + setIsFirstAttempt(false); + if (setIsDataInResponse) { + setIsDataInResponse(true); + } + } + }, [actionList, error, isFetching, setIsDataInResponse]); + // handle auto refresh data const onRefresh = useCallback(() => { if (dateRangePickerState.autoRefreshOptions.enabled) { @@ -216,6 +239,15 @@ export const ResponseActionsLog = memo< }, [setQueryParams] ); + + // handle on change users filter + const onChangeUsersFilter = useCallback( + (selectedUserIds: string[]) => { + setQueryParams((prevState) => ({ ...prevState, userIds: selectedUserIds })); + }, + [setQueryParams] + ); + // total actions const totalItemCount = useMemo(() => actionList?.total ?? 0, [actionList]); @@ -586,27 +618,10 @@ export const ResponseActionsLog = memo< [getTestId, pagedResultsCount.fromCount, pagedResultsCount.toCount, totalItemCount] ); - useEffect(() => { - if ( - !isFetching && - error?.body?.statusCode === 404 && - error?.body?.message === 'index_not_found_exception' - ) { - if (setIsDataCallback) { - setIsDataCallback(false); - } - } else if (!isFetching && actionList) { - setIsFirstAttempt(false); - if (setIsDataCallback) { - setIsDataCallback(true); - } - } - }, [actionList, error, isFetching, setIsDataCallback]); - if (error?.body?.statusCode === 404 && error?.body?.message === 'index_not_found_exception') { - return ; + return ; } else if (isFetching && isFirstAttempt) { - return ; + return ; } return ( <> @@ -618,6 +633,7 @@ export const ResponseActionsLog = memo< onChangeHostsFilter={onChangeHostsFilter} onChangeCommandsFilter={onChangeCommandsFilter} onChangeStatusesFilter={onChangeStatusesFilter} + onChangeUsersFilter={onChangeUsersFilter} onRefresh={onRefresh} onRefreshChange={onRefreshChange} onTimeChange={onTimeChange} diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx index 9efc4356c21a2..542f0d72bf0be 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx @@ -160,7 +160,6 @@ export const UX_MESSAGES = Object.freeze({ }), }); -// TODO: Add more filter names here (hosts, statuses) etc export const FILTER_NAMES = Object.freeze({ actions: i18n.translate('xpack.securitySolution.responseActionsList.list.filter.actions', { defaultMessage: 'Actions', @@ -171,4 +170,7 @@ export const FILTER_NAMES = Object.freeze({ statuses: i18n.translate('xpack.securitySolution.responseActionsList.list.filter.statuses', { defaultMessage: 'Statuses', }), + users: i18n.translate('xpack.securitySolution.responseActionsList.list.filter.users', { + defaultMessage: 'Filter by user or comma separated list of users', + }), }); diff --git a/x-pack/plugins/security_solution/public/management/components/management_empty_state_wrapper.tsx b/x-pack/plugins/security_solution/public/management/components/management_empty_state_wrapper.tsx index 19b0cf44736f0..db25aea95f917 100644 --- a/x-pack/plugins/security_solution/public/management/components/management_empty_state_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/management/components/management_empty_state_wrapper.tsx @@ -13,12 +13,20 @@ export const StyledEuiFlexGroup = styled(EuiFlexGroup)` min-height: calc(100vh - 140px); `; -export const ManagementEmptyStateWrapper = memo(({ children }) => { - return ( - - {children} - - ); -}); +export const ManagementEmptyStateWrapper = memo( + ({ + children, + 'data-test-subj': dataTestSubj, + }: { + children: React.ReactNode; + 'data-test-subj'?: string; + }) => { + return ( + + {children} + + ); + } +); ManagementEmptyStateWrapper.displayName = 'ManagementEmptyStateWrapper'; diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx index 23f8ea83a7094..4c7ac15a504a7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx @@ -29,7 +29,8 @@ import type { HttpFetchOptionsWithPath } from '@kbn/core/public'; jest.mock('../../../../../common/components/user_privileges'); -describe('When on the host isolation exceptions entry form', () => { +// FLAKY: https://github.com/elastic/kibana/issues/140907 +describe.skip('When on the host isolation exceptions entry form', () => { let render: () => Promise>; let renderResult: ReturnType; let history: AppContextTestRender['history']; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx deleted file mode 100644 index e83482e560cb0..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.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, { memo, useEffect } from 'react'; -import { EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; - -/** - * Exports Endpoint-specific package policy instructions - * for use in the Ingest app create / edit package policy - */ -export const EndpointPolicyCreateExtension = memo( - ({ newPolicy, onChange }) => { - // Fleet will initialize the create form with a default name for the integratin policy, however, - // for endpoint security, we want the user to explicitely type in a name, so we blank it out - // only during 1st component render (thus why the eslint disabled rule below). - useEffect(() => { - onChange({ - isValid: false, - updatedPolicy: { - ...newPolicy, - name: '', - }, - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( - <> - - - -

- -

-
-
- - ); - } -); -EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx new file mode 100644 index 0000000000000..9a4dc273740e5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx @@ -0,0 +1,370 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, useState, useEffect, useRef, useCallback } from 'react'; +import { + EuiForm, + EuiCheckbox, + EuiRadio, + EuiSelect, + EuiText, + EuiTitle, + EuiSpacer, + EuiFormRow, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import styled from 'styled-components'; +import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; +import { useLicense } from '../../../../../../common/hooks/use_license'; +import { + ALL_EVENTS, + CLOUD_SECURITY, + EDR_COMPLETE, + NGAV, + EDR_ESSENTIAL, + ENDPOINT, + INTERACTIVE_ONLY, + PREVENT_MALICIOUS_BEHAVIOUR, +} from './translations'; + +const PREFIX = 'endpoint_policy_create_extension'; + +const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; + +const environmentMapping = { + cloud: CLOUD_SECURITY, + endpoint: ENDPOINT, +}; + +const endpointPresetsMapping = { + NGAV, + EDREssential: EDR_ESSENTIAL, + EDRComplete: EDR_COMPLETE, +}; + +const cloudEventMapping = { + INTERACTIVE_ONLY, + ALL_EVENTS, +}; + +type EndpointPreset = keyof typeof endpointPresetsMapping; +type CloudEvent = keyof typeof cloudEventMapping; +type Environment = keyof typeof environmentMapping; + +const environmentOptions: Array<{ value: Environment; text: string }> = [ + { value: 'endpoint', text: ENDPOINT }, + { value: 'cloud', text: CLOUD_SECURITY }, +]; + +const HelpTextWithPadding = styled.div` + padding-left: ${(props) => props.theme.eui.euiSizeL}; +`; + +/** + * Exports Endpoint-specific package policy instructions + * for use in the Ingest app create / edit package policy + */ +export const EndpointPolicyCreateExtension = memo( + ({ newPolicy, onChange }) => { + const isPlatinumPlus = useLicense().isPlatinumPlus(); + + // / Endpoint Radio Options (NGAV and EDRs) + const [endpointPreset, setEndpointPreset] = useState('NGAV'); + const [behaviorProtectionChecked, setBehaviorProtectionChecked] = useState(false); + const [selectedCloudEvent, setSelectedCloudEvent] = useState('INTERACTIVE_ONLY'); + const [selectedEnvironment, setSelectedEnvironment] = useState('endpoint'); + const initialRender = useRef(true); + + // Fleet will initialize the create form with a default name for the integratin policy, however, + // for endpoint security, we want the user to explicitely type in a name, so we blank it out + // only during 1st component render (thus why the eslint disabled rule below). + // Default values for config are endpoint + NGAV + useEffect(() => { + if (initialRender.current) { + onChange({ + isValid: false, + updatedPolicy: { + ...newPolicy, + name: '', + inputs: [ + { + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + config: { + _config: { + value: { + type: 'endpoint', + endpointConfig: { + preset: 'NGAV', + }, + }, + }, + }, + }, + ], + }, + }); + } + }, [onChange, newPolicy]); + + useEffect(() => { + // Skip trigerring this onChange on the initial render + if (initialRender.current) { + initialRender.current = false; + } else { + onChange({ + isValid: true, + updatedPolicy: { + ...newPolicy, + inputs: [ + { + ...newPolicy.inputs[0], + config: { + _config: { + value: { + type: selectedEnvironment, + ...(selectedEnvironment === 'cloud' + ? { + cloudConfig: { + preventions: { + behavior_protection: behaviorProtectionChecked, + }, + }, + eventFilters: { + nonInteractiveSession: selectedCloudEvent === 'INTERACTIVE_ONLY', + }, + } + : { + endpointConfig: { + preset: endpointPreset, + }, + }), + }, + }, + }, + }, + ], + }, + }); + } + }, [ + selectedEnvironment, + behaviorProtectionChecked, + selectedCloudEvent, + endpointPreset, + onChange, + newPolicy, + ]); + + const onChangeEnvironment = useCallback((e: React.ChangeEvent) => { + setSelectedEnvironment(e?.target?.value as Environment); + }, []); + const onChangeCloudEvent = useCallback((e: React.ChangeEvent) => { + setSelectedCloudEvent(e.target.value as CloudEvent); + }, []); + const onChangeEndpointPreset = useCallback((e: React.ChangeEvent) => { + setEndpointPreset(e.target.value as EndpointPreset); + }, []); + const onChangeMaliciousBehavior = useCallback((e: React.ChangeEvent) => { + setBehaviorProtectionChecked((checked) => !checked); + }, []); + + const getEndpointPresetsProps = useCallback( + (preset: EndpointPreset) => ({ + id: `${PREFIX}_endpoint_preset_${preset}`, + label: endpointPresetsMapping[preset], + value: preset, + checked: endpointPreset === preset, + onChange: onChangeEndpointPreset, + }), + [endpointPreset, onChangeEndpointPreset] + ); + + const getCloudEventsProps = useCallback( + (cloudEvent: CloudEvent) => ({ + id: `${PREFIX}_cloud_event_${cloudEvent}`, + label: cloudEventMapping[cloudEvent], + value: cloudEvent, + checked: selectedCloudEvent === cloudEvent, + onChange: onChangeCloudEvent, + }), + [selectedCloudEvent, onChangeCloudEvent] + ); + + return ( + + +

+ +

+
+ + +

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

+
+ + + } + > + + + {selectedEnvironment === 'endpoint' ? ( + <> + + + + + } + > + + + + + + + } + > + + + + + + + } + > + + + + ) : ( + <> + + +

+ +

+
+ + + + + } + > + + + + + + + } + > + + + {isPlatinumPlus && ( + <> + + +

+ +

+
+ + +

+ +

+
+ + + + )} + + )} + +
+ ); + }, + (prevProps, nextProps) => { + return prevProps.newPolicy.name === nextProps.newPolicy.name; + } +); +EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx new file mode 100644 index 0000000000000..9be04def1c64e --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { EndpointPolicyCreateExtension } from './endpoint_policy_create_extension'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.ts new file mode 100644 index 0000000000000..b50835b36995b --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.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 { i18n } from '@kbn/i18n'; + +export const NGAV = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionNGAV', + { + defaultMessage: 'NGAV', + } +); + +export const EDR_ESSENTIAL = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDREssential', + { + defaultMessage: 'EDR Essential', + } +); +export const EDR_COMPLETE = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDRComplete', + { + defaultMessage: 'EDR Complete', + } +); + +export const ENDPOINT = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + { + defaultMessage: 'Endpoint', + } +); +export const CLOUD_SECURITY = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudSecurityDropdownOption', + { + defaultMessage: 'Cloud Security', + } +); +export const INTERACTIVE_ONLY = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersInteractiveOnly', + { + defaultMessage: 'Interactive only', + } +); +export const ALL_EVENTS = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersAllEvents', + { + defaultMessage: 'All events', + } +); +export const PREVENT_MALWARE = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMalware', + { + defaultMessage: 'Prevent Malware', + } +); +export const PREVENT_MALICIOUS_BEHAVIOUR = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMaliciousBehaviour', + { + defaultMessage: 'Prevent Malicious Behaviour', + } +); diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx index ebb365cd44c54..734db973826c9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import * as reactTestingLibrary from '@testing-library/react'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import userEvent from '@testing-library/user-event'; +import type { IHttpFetchError } from '@kbn/core-http-browser'; import { type AppContextTestRender, createAppRootMockRenderer, @@ -22,7 +23,7 @@ import { useGetEndpointsList } from '../../../hooks/endpoint/use_get_endpoints_l let mockUseGetEndpointActionList: { isFetched?: boolean; isFetching?: boolean; - error?: null; + error?: Partial | null; data?: ActionListApiResponse; refetch: () => unknown; }; @@ -160,6 +161,32 @@ describe('Action history page', () => { jest.clearAllMocks(); }); + describe('Hide/Show header', () => { + it('should show header when data is in', () => { + reactTestingLibrary.act(() => { + history.push('/administration/action_history?page=3&pageSize=20'); + }); + render(); + const { getByTestId } = renderResult; + expect(getByTestId('responseActionsPage-header')).toBeTruthy(); + }); + + it('should not show header when there is no actions index', () => { + reactTestingLibrary.act(() => { + history.push('/administration/action_history?page=3&pageSize=20'); + }); + mockUseGetEndpointActionList = { + ...baseMockedActionList, + error: { + body: { statusCode: 404, message: 'index_not_found_exception' }, + }, + }; + render(); + const { queryByTestId } = renderResult; + expect(queryByTestId('responseActionsPage-header')).toBeNull(); + }); + }); + describe('Read from URL params', () => { it('should read and set paging values from URL params', () => { reactTestingLibrary.act(() => { @@ -263,7 +290,18 @@ describe('Action history page', () => { expect(history.location.search).toEqual('?statuses=pending,failed'); }); - // TODO: add tests for users when that filter is added + it('should set selected users search input strings to URL params ', () => { + const filterPrefix = 'users-filter'; + reactTestingLibrary.act(() => { + history.push('/administration/action_history?users=userX,userY'); + }); + + render(); + const { getByTestId } = renderResult; + const usersInput = getByTestId(`${testPrefix}-${filterPrefix}-search`); + expect(usersInput).toHaveValue('userX,userY'); + expect(history.location.search).toEqual('?users=userX,userY'); + }); it('should read and set relative date ranges filter values from URL params', () => { reactTestingLibrary.act(() => { @@ -371,7 +409,16 @@ describe('Action history page', () => { expect(history.location.search).toEqual('?statuses=failed%2Cpending%2Csuccessful'); }); - // TODO: add tests for users when that filter is added + it('should set selected users search input strings to URL params ', () => { + const filterPrefix = 'users-filter'; + render(); + const { getByTestId } = renderResult; + const usersInput = getByTestId(`${testPrefix}-${filterPrefix}-search`); + userEvent.type(usersInput, ' , userX , userY, ,'); + userEvent.type(usersInput, '{enter}'); + + expect(history.location.search).toEqual('?users=userX%2CuserY'); + }); it('should set selected relative date range filter options to URL params ', async () => { const { getByTestId } = render(); diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx index 595f5cee928c2..e1f3705b4489c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx @@ -13,7 +13,7 @@ import { UX_MESSAGES } from '../../../components/endpoint_response_actions_list/ export const ResponseActionsListPage = () => { const [hideHeader, setHideHeader] = useState(true); - const setIsDataCallback = useCallback((isData: boolean) => { + const resetPageHeader = useCallback((isData: boolean) => { setHideHeader(!isData); }, []); return ( @@ -26,7 +26,7 @@ export const ResponseActionsListPage = () => { ); diff --git a/x-pack/plugins/security_solution/public/network/pages/details/index.tsx b/x-pack/plugins/security_solution/public/network/pages/details/index.tsx index b0dda455293d9..c7c435b608d7e 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/index.tsx @@ -5,13 +5,15 @@ * 2.0. */ -import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import React, { useCallback, useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; +import { AlertsByStatus } from '../../../overview/components/detection_response/alerts_by_status'; +import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index'; import { InputsModelId } from '../../../common/store/inputs/constants'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import { LastEventIndexKey } from '../../../../common/search_strategy'; @@ -44,7 +46,9 @@ import { LandingPageComponent } from '../../../common/components/landing_page'; import { SecuritySolutionTabNavigation } from '../../../common/components/navigation'; import { getNetworkDetailsPageFilter } from '../../../common/components/visualization_actions/utils'; import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions'; +import { AlertCountByRuleByStatus } from '../../../common/components/alert_count_by_status'; import { useMlCapabilities } from '../../../common/components/ml/hooks/use_ml_capabilities'; +import { useAlertsPrivileges } from '../../../detections/containers/detection_engine/alerts/use_alerts_privileges'; import { navTabsNetworkDetails } from './nav_tabs'; import { NetworkDetailsTabs } from './details_tabs'; import { useInstalledSecurityJobsIds } from '../../../common/components/ml/hooks/use_installed_security_jobs'; @@ -67,6 +71,10 @@ const NetworkDetailsComponent: React.FC = () => { [] ); + const { signalIndexName } = useSignalIndex(); + const { hasKibanaREAD, hasIndexRead } = useAlertsPrivileges(); + const canReadAlerts = hasKibanaREAD && hasIndexRead; + const query = useDeepEqualSelector(getGlobalQuerySelector); const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); @@ -137,6 +145,14 @@ const NetworkDetailsComponent: React.FC = () => { [isInitializing, filterQuery] ); + const entityFilter = useMemo( + () => ({ + field: `${flowTarget}.ip`, + value: detailName, + }), + [detailName, flowTarget] + ); + return (
{indicesExist ? ( @@ -161,6 +177,7 @@ const NetworkDetailsComponent: React.FC = () => { > + { narrowDateRange={narrowDateRange} indexPatterns={selectedPatterns} /> + + + {canReadAlerts && ( + <> + + + + + + + + + + + )} + diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx index 7bb8948825aae..0e348b123c3c0 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx @@ -5,7 +5,16 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiProgress, EuiSpacer, EuiText } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiProgress, + EuiSpacer, + EuiText, + useIsWithinMaxBreakpoint, + useIsWithinMinBreakpoint, +} from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import type { ShapeTreeNode } from '@elastic/charts'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; @@ -13,15 +22,16 @@ import styled from 'styled-components'; import type { FillColor } from '../../../../common/components/charts/donutchart'; import { DonutChart } from '../../../../common/components/charts/donutchart'; import { SecurityPageName } from '../../../../../common/constants'; -import { useNavigation } from '../../../../common/lib/kibana'; import { HeaderSection } from '../../../../common/components/header_section'; import { HoverVisibilityContainer } from '../../../../common/components/hover_visibility_container'; import { BUTTON_CLASS as INPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; import type { LegendItem } from '../../../../common/components/charts/legend_item'; +import type { EntityFilter } from './use_alerts_by_status'; import { useAlertsByStatus } from './use_alerts_by_status'; import { ALERTS, ALERTS_TEXT, + ALERTS_BY_STATUS_TEXT, STATUS_ACKNOWLEDGED, STATUS_CLOSED, STATUS_CRITICAL_LABEL, @@ -31,16 +41,16 @@ import { STATUS_OPEN, } from '../translations'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; -import { getDetectionEngineUrl, useFormatUrl } from '../../../../common/components/link_to'; import { VIEW_ALERTS } from '../../../pages/translations'; -import { LastUpdatedAt, SEVERITY_COLOR } from '../utils'; +import { SEVERITY_COLOR } from '../utils'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { ChartLabel } from './chart_label'; import { Legend } from '../../../../common/components/charts/legend'; import { emptyDonutColor } from '../../../../common/components/charts/donutchart_empty'; -import { LinkButton } from '../../../../common/components/links'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; +import { LinkButton, useGetSecuritySolutionLinkProps } from '../../../../common/components/links'; +import { useNavigateToTimeline } from '../hooks/use_navigate_to_timeline'; -const donutHeight = 120; const StyledFlexItem = styled(EuiFlexItem)` padding: 0 4px; `; @@ -52,6 +62,7 @@ const StyledLegendFlexItem = styled(EuiFlexItem)` interface AlertsByStatusProps { signalIndexName: string | null; + entityFilter?: EntityFilter; } const legendField = 'kibana.alert.severity'; @@ -63,28 +74,31 @@ const chartConfigs: Array<{ key: Severity; label: string; color: string }> = [ ]; const DETECTION_RESPONSE_ALERTS_BY_STATUS_ID = 'detection-response-alerts-by-status'; -export const AlertsByStatus = ({ signalIndexName }: AlertsByStatusProps) => { +const eventKindSignalFilter: EntityFilter = { + field: 'event.kind', + value: 'signal', +}; + +export const AlertsByStatus = ({ signalIndexName, entityFilter }: AlertsByStatusProps) => { const { toggleStatus, setToggleStatus } = useQueryToggle(DETECTION_RESPONSE_ALERTS_BY_STATUS_ID); - const { formatUrl, search: urlSearch } = useFormatUrl(SecurityPageName.alerts); - const { navigateTo } = useNavigation(); - const goToAlerts = useCallback( - (ev) => { - ev.preventDefault(); - navigateTo({ - deepLinkId: SecurityPageName.alerts, - path: getDetectionEngineUrl(urlSearch), - }); - }, - [navigateTo, urlSearch] - ); + const { openEntityInTimeline } = useNavigateToTimeline(); + const { onClick: goToAlerts, href } = useGetSecuritySolutionLinkProps()({ + deepLinkId: SecurityPageName.alerts, + }); + + const isLargerBreakpoint = useIsWithinMinBreakpoint('xl'); + const isSmallBreakpoint = useIsWithinMaxBreakpoint('s'); + const donutHeight = isSmallBreakpoint || isLargerBreakpoint ? 120 : 90; const detailsButtonOptions = useMemo( () => ({ name: VIEW_ALERTS, - href: formatUrl(getDetectionEngineUrl()), - onClick: goToAlerts, + href: entityFilter ? undefined : href, + onClick: entityFilter + ? () => openEntityInTimeline([entityFilter, eventKindSignalFilter]) + : goToAlerts, }), - [formatUrl, goToAlerts] + [entityFilter, href, goToAlerts, openEntityInTimeline] ); const { @@ -92,9 +106,10 @@ export const AlertsByStatus = ({ signalIndexName }: AlertsByStatusProps) => { isLoading: loading, updatedAt, } = useAlertsByStatus({ + entityFilter, signalIndexName, - queryId: DETECTION_RESPONSE_ALERTS_BY_STATUS_ID, skip: !toggleStatus, + queryId: DETECTION_RESPONSE_ALERTS_BY_STATUS_ID, }); const legendItems: LegendItem[] = useMemo( () => @@ -131,7 +146,7 @@ export const AlertsByStatus = ({ signalIndexName }: AlertsByStatusProps) => { )} } inspectMultiple diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status.ts index ab9dd704dcc23..bf926f33e3a5e 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/use_alerts_by_status.ts @@ -26,11 +26,35 @@ export const severityLabels: Record = { low: STATUS_LOW_LABEL, }; -export const getAlertsByStatusQuery = ({ from, to }: { from: string; to: string }) => ({ +export interface EntityFilter { + field: string; + value: string; +} + +export const getAlertsByStatusQuery = ({ + from, + to, + entityFilter, +}: { + from: string; + to: string; + entityFilter?: EntityFilter; +}) => ({ size: 0, query: { bool: { - filter: [{ range: { '@timestamp': { gte: from, lte: to } } }], + filter: [ + { range: { '@timestamp': { gte: from, lte: to } } }, + ...(entityFilter + ? [ + { + term: { + [entityFilter.field]: entityFilter.value, + }, + }, + ] + : []), + ], }, }, aggs: { @@ -79,6 +103,7 @@ export interface UseAlertsByStatusProps { queryId: string; signalIndexName: string | null; skip?: boolean; + entityFilter?: EntityFilter; } export type UseAlertsByStatus = (props: UseAlertsByStatusProps) => { @@ -88,6 +113,7 @@ export type UseAlertsByStatus = (props: UseAlertsByStatusProps) => { }; export const useAlertsByStatus: UseAlertsByStatus = ({ + entityFilter, queryId, signalIndexName, skip = false, @@ -107,6 +133,7 @@ export const useAlertsByStatus: UseAlertsByStatus = ({ query: getAlertsByStatusQuery({ from, to, + entityFilter, }), indexName: signalIndexName, skip, @@ -118,9 +145,10 @@ export const useAlertsByStatus: UseAlertsByStatus = ({ getAlertsByStatusQuery({ from, to, + entityFilter, }) ); - }, [setAlertsQuery, from, to]); + }, [setAlertsQuery, from, to, entityFilter]); useEffect(() => { if (data == null) { diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx index e71935d217c55..459131164dbe2 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx @@ -13,7 +13,7 @@ import styled from 'styled-components'; import { FormattedNumber } from '@kbn/i18n-react'; import numeral from '@elastic/numeral'; import { BarChart } from '../../../../common/components/charts/barchart'; -import { LastUpdatedAt } from '../utils'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { HeaderSection } from '../../../../common/components/header_section'; import { diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx index e5fdeb6c31638..c6d819699a8db 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx @@ -25,12 +25,12 @@ import { FormattedCount } from '../../../../common/components/formatted_number'; import { HeaderSection } from '../../../../common/components/header_section'; import { HoverVisibilityContainer } from '../../../../common/components/hover_visibility_container'; import { BUTTON_CLASS as INPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { CaseDetailsLink } from '../../../../common/components/links'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import type { NavigateTo, GetAppUrl } from '../../../../common/lib/kibana'; import { useNavigation } from '../../../../common/lib/kibana'; import * as i18n from '../translations'; -import { LastUpdatedAt } from '../utils'; import { StatusBadge } from './status_badge'; import type { CaseItem } from './use_case_items'; import { useCaseItems } from './use_case_items'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx index 5062c4ab83840..f74936d85a937 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/hooks/use_navigate_to_timeline.tsx @@ -5,19 +5,35 @@ * 2.0. */ +import { useMemo } from 'react'; import { useDispatch } from 'react-redux'; -import { getDataProvider } from '../../../../common/components/event_details/table/use_action_cell_data_provider'; -import { sourcererActions } from '../../../../common/store/sourcerer'; +import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; +import { sourcererActions } from '../../../../common/store/sourcerer'; +import { getDataProvider } from '../../../../common/components/event_details/table/use_action_cell_data_provider'; import type { DataProvider } from '../../../../../common/types/timeline'; import { TimelineId, TimelineType } from '../../../../../common/types/timeline'; import { useCreateTimeline } from '../../../../timelines/components/timeline/properties/use_create_timeline'; import { updateProviders } from '../../../../timelines/store/timeline/actions'; +import { sourcererSelectors } from '../../../../common/store'; + +export interface Filter { + field: string; + value: string; +} export const useNavigateToTimeline = () => { const dispatch = useDispatch(); + const getDataViewsSelector = useMemo( + () => sourcererSelectors.getSourcererDataViewsSelector(), + [] + ); + const { defaultDataView, signalIndexName } = useDeepEqualSelector((state) => + getDataViewsSelector(state) + ); + const clearTimeline = useCreateTimeline({ timelineId: TimelineId.active, timelineType: TimelineType.default, @@ -33,17 +49,32 @@ export const useNavigateToTimeline = () => { providers: [dataProvider], }) ); - // Only show detection alerts - // (This is required so the timeline event count matches the prevalence count) + dispatch( sourcererActions.setSelectedDataView({ id: SourcererScopeName.timeline, - selectedDataViewId: 'security-solution-default', - selectedPatterns: ['.alerts-security.alerts-default'], + selectedDataViewId: defaultDataView.id, + selectedPatterns: [signalIndexName || ''], }) ); }; + const openEntityInTimeline = (entityFilters: [Filter, ...Filter[]]) => { + const mainFilter = entityFilters.shift(); + + if (mainFilter) { + const dataProvider = getDataProvider(mainFilter.field, '', mainFilter.value); + + for (const filter of entityFilters) { + dataProvider.and.push(getDataProvider(filter.field, '', filter.value)); + } + + navigateToTimeline(dataProvider); + } + }; + + // TODO: Replace the usage of functions with openEntityInTimeline + const openHostInTimeline = ({ hostName, severity }: { hostName: string; severity?: string }) => { const dataProvider = getDataProvider('host.name', '', hostName); @@ -70,6 +101,7 @@ export const useNavigateToTimeline = () => { }; return { + openEntityInTimeline, openHostInTimeline, openRuleInTimeline, openUserInTimeline, diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx index 3ae0d5e1384c3..b5ec1de73fa39 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx @@ -23,11 +23,12 @@ import { FormattedCount } from '../../../../common/components/formatted_number'; import { HeaderSection } from '../../../../common/components/header_section'; import { HoverVisibilityContainer } from '../../../../common/components/hover_visibility_container'; import { BUTTON_CLASS as INPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { HostDetailsLink } from '../../../../common/components/links'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { useNavigateToTimeline } from '../hooks/use_navigate_to_timeline'; import * as i18n from '../translations'; -import { ITEMS_PER_PAGE, LastUpdatedAt, SEVERITY_COLOR } from '../utils'; +import { ITEMS_PER_PAGE, SEVERITY_COLOR } from '../utils'; import type { HostAlertsItem } from './use_host_alerts_items'; import { useHostAlertsItems } from './use_host_alerts_items'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx index 3e9e79a39de58..59a92896ddb85 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx @@ -22,7 +22,7 @@ import { FormattedRelative } from '@kbn/i18n-react'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import { HeaderSection } from '../../../../common/components/header_section'; -import { LastUpdatedAt, SEVERITY_COLOR } from '../utils'; +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'; @@ -31,7 +31,8 @@ import { useNavigation } from '../../../../common/lib/kibana'; import { SecurityPageName } from '../../../../../common/constants'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { HoverVisibilityContainer } from '../../../../common/components/hover_visibility_container'; -import { BUTTON_CLASS as INPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; +import { BUTTON_CLASS as INSPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { useNavigateToTimeline } from '../hooks/use_navigate_to_timeline'; @@ -125,7 +126,7 @@ export const RuleAlertsTable = React.memo(({ signalIndexNa ); return ( - + export const ALERTS_TEXT = i18n.translate('xpack.securitySolution.detectionResponse.alerts', { defaultMessage: 'Alerts', }); +export const ALERTS_BY_STATUS_TEXT = i18n.translate( + 'xpack.securitySolution.detectionResponse.alertsByStatus', + { + defaultMessage: 'Alerts by Status', + } +); + export const UPDATING = i18n.translate('xpack.securitySolution.detectionResponse.updating', { defaultMessage: 'Updating...', }); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx index a279b6ced4a1c..c50f5976360ed 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx @@ -23,11 +23,12 @@ import { FormattedCount } from '../../../../common/components/formatted_number'; import { HeaderSection } from '../../../../common/components/header_section'; import { HoverVisibilityContainer } from '../../../../common/components/hover_visibility_container'; import { BUTTON_CLASS as INPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { UserDetailsLink } from '../../../../common/components/links'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { useNavigateToTimeline } from '../hooks/use_navigate_to_timeline'; import * as i18n from '../translations'; -import { ITEMS_PER_PAGE, LastUpdatedAt, SEVERITY_COLOR } from '../utils'; +import { ITEMS_PER_PAGE, SEVERITY_COLOR } from '../utils'; import type { UserAlertsItem } from './use_user_alerts_items'; import { useUserAlertsItems } from './use_user_alerts_items'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/utils.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/utils.tsx index 0a602b21f676f..76b690e0fbf0a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/utils.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/utils.tsx @@ -5,13 +5,6 @@ * 2.0. */ -import React from 'react'; - -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { FormattedRelative } from '@kbn/i18n-react'; - -import * as i18n from './translations'; - export const SEVERITY_COLOR = { critical: '#E7664C', high: '#DA8B45', @@ -22,28 +15,6 @@ export const SEVERITY_COLOR = { export const ITEMS_PER_PAGE = 4; const MAX_ALLOWED_RESULTS = 100; -export interface LastUpdatedAtProps { - updatedAt: number; - isUpdating: boolean; -} - -export const LastUpdatedAt: React.FC = ({ isUpdating, updatedAt }) => ( - - {isUpdating ? ( - {i18n.UPDATING} - ) : ( - - <>{i18n.UPDATED} - - - )} - -); - /** * While there could be more than 100 hosts or users we only want to show 25 pages of results, * and the host count cardinality result will always be the total count diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/anomalies/index.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/anomalies/index.tsx index dea9314a3645f..2d8491879d060 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/anomalies/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/anomalies/index.tsx @@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiInMemoryTable, EuiPanel } from '@elastic/ import { ML_PAGES, useMlHref } from '@kbn/ml-plugin/public'; import { HeaderSection } from '../../../../common/components/header_section'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; -import { LastUpdatedAt } from '../../detection_response/utils'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import * as i18n from './translations'; import { useNotableAnomaliesSearch } from '../../../../common/components/ml/anomaly/use_anomalies_search'; import { useAnomaliesColumns } from './columns'; diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx index 9a0552f854a08..123f190446255 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx @@ -14,7 +14,7 @@ import { LinkButton, useGetSecuritySolutionLinkProps } from '../../../../common/ import { getTabsOnHostsUrl } from '../../../../common/components/link_to/redirect_to_hosts'; import { HostsTableType, HostsType } from '../../../../hosts/store/model'; import { getHostRiskScoreColumns } from './columns'; -import { LastUpdatedAt } from '../../detection_response/utils'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { HeaderSection } from '../../../../common/components/header_section'; import { useHostRiskScore, useHostRiskScoreKpi } from '../../../../risk_score/containers'; diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx index a8b85bd2ac281..fe4a72f466ea0 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx @@ -10,7 +10,7 @@ import { useDispatch } from 'react-redux'; import { RiskScoresDeprecated } from '../../../../common/components/risk_score/risk_score_deprecated'; import { SeverityFilterGroup } from '../../../../common/components/severity/severity_filter_group'; import { LinkButton, useGetSecuritySolutionLinkProps } from '../../../../common/components/links'; -import { LastUpdatedAt } from '../../detection_response/utils'; +import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { HeaderSection } from '../../../../common/components/header_section'; import type { RiskSeverity } from '../../../../../common/search_strategy'; import { RiskScoreEntity } from '../../../../../common/search_strategy'; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/action.ts b/x-pack/plugins/security_solution/public/resolver/store/data/action.ts index c93ba64ba801e..253135516530d 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/action.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/action.ts @@ -11,7 +11,7 @@ import type { SafeResolverEvent, ResolverSchema, } from '../../../../common/endpoint/types'; -import type { TreeFetcherParameters, PanelViewAndParameters } from '../../types'; +import type { TreeFetcherParameters, PanelViewAndParameters, TimeFilters } from '../../types'; interface ServerReturnedResolverData { readonly type: 'serverReturnedResolverData'; @@ -32,6 +32,12 @@ interface ServerReturnedResolverData { * The database parameters that was used to fetch the resolver tree */ parameters: TreeFetcherParameters; + + /** + * If the user supplied date range results in 0 process events, + * an unbounded request is made, and the time range of the result set displayed to the user through this value. + */ + detectedBounds?: TimeFilters; }; } diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts index 52cb97dbc24f5..f24925441b8fb 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts @@ -10,7 +10,7 @@ import { createStore } from 'redux'; import { RelatedEventCategory } from '../../../../common/endpoint/generate_data'; import { dataReducer } from './reducer'; import * as selectors from './selectors'; -import type { DataState, GeneratedTreeMetadata } from '../../types'; +import type { DataState, GeneratedTreeMetadata, TimeFilters } from '../../types'; import type { DataAction } from './action'; import { generateTreeWithDAL } from '../../data_access_layer/mocks/generator_tree'; import { endpointSourceSchema, winlogSourceSchema } from '../../mocks/tree_schema'; @@ -24,11 +24,19 @@ type SourceAndSchemaFunction = () => { schema: ResolverSchema; dataSource: strin */ describe('Resolver Data Middleware', () => { let store: Store; - let dispatchTree: (tree: NewResolverTree, sourceAndSchema: SourceAndSchemaFunction) => void; + let dispatchTree: ( + tree: NewResolverTree, + sourceAndSchema: SourceAndSchemaFunction, + detectedBounds?: TimeFilters + ) => void; beforeEach(() => { store = createStore(dataReducer, undefined); - dispatchTree = (tree: NewResolverTree, sourceAndSchema: SourceAndSchemaFunction) => { + dispatchTree = ( + tree: NewResolverTree, + sourceAndSchema: SourceAndSchemaFunction, + detectedBounds?: TimeFilters + ) => { const { schema, dataSource } = sourceAndSchema(); const action: DataAction = { type: 'serverReturnedResolverData', @@ -41,6 +49,7 @@ describe('Resolver Data Middleware', () => { indices: [], filters: {}, }, + detectedBounds, }, }; store.dispatch(action); @@ -76,6 +85,25 @@ describe('Resolver Data Middleware', () => { expect(selectors.hasMoreGenerations(store.getState())).toBeFalsy(); }); }); + describe('when a tree with detected bounds is loaded', () => { + it('should set the detected bounds when in the payload', () => { + dispatchTree(generatedTreeMetadata.formattedTree, endpointSourceSchema, { + from: 'Sep 19, 2022 @ 20:49:13.452', + to: 'Sep 19, 2022 @ 20:49:13.452', + }); + expect(selectors.detectedBounds(store.getState())).toBeTruthy(); + }); + + it('should clear the previous detected bounds when a new response without detected bounds is recevied', () => { + dispatchTree(generatedTreeMetadata.formattedTree, endpointSourceSchema, { + from: 'Sep 19, 2022 @ 20:49:13.452', + to: 'Sep 19, 2022 @ 20:49:13.452', + }); + expect(selectors.detectedBounds(store.getState())).toBeTruthy(); + dispatchTree(generatedTreeMetadata.formattedTree, endpointSourceSchema); + expect(selectors.detectedBounds(store.getState())).toBeFalsy(); + }); + }); }); describe('when the generated tree has dimensions larger than the limits sent to the server', () => { diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts index 64fe9080a3d5d..f2abb722b09bb 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts @@ -20,6 +20,7 @@ const initialState: DataState = { }, resolverComponentInstanceID: undefined, indices: [], + detectedBounds: undefined, }; /* eslint-disable complexity */ export const dataReducer: Reducer = (state = initialState, action) => { @@ -101,6 +102,7 @@ export const dataReducer: Reducer = (state = initialS // This cannot model multiple in-flight requests pendingRequestParameters: undefined, }, + detectedBounds: action.payload.detectedBounds, }; return nextState; } else if (action.type === 'serverFailedToReturnResolverData') { diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts index bbec11486bcce..511cebc2c6448 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts @@ -6,7 +6,7 @@ */ import * as selectors from './selectors'; -import type { DataState, TimeRange } from '../../types'; +import type { DataState } from '../../types'; import type { ResolverAction } from '../actions'; import { dataReducer } from './reducer'; import { createStore } from 'redux'; @@ -425,7 +425,7 @@ describe('data state', () => { expect(selectors.timeRangeFilters(state())?.to).toBe(new Date(maxDate).toISOString()); }); describe('when resolver receives time range filters', () => { - const timeRangeFilters: TimeRange = { + const timeRangeFilters = { to: 'to', from: 'from', }; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts index 72afd77482c8f..0d43f22747f06 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts @@ -46,6 +46,10 @@ export function isTreeLoading(state: DataState): boolean { return state.tree?.pendingRequestParameters !== undefined; } +export function detectedBounds(state: DataState) { + return state.detectedBounds; +} + /** * If a request was made and it threw an error or returned a failure response code. */ diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts index c2403920bac55..e4da1af5f4d79 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts @@ -14,6 +14,7 @@ import type { } from '../../../../common/endpoint/types'; import type { ResolverState, DataAccessLayer } from '../../types'; import * as selectors from '../selectors'; +import { firstNonNullValue } from '../../../../common/endpoint/models/ecs_safety_helpers'; import type { ResolverAction } from '../actions'; import { ancestorsRequestAmount, descendantsRequestAmount } from '../../models/resolver_tree'; @@ -83,15 +84,56 @@ export function ResolverTreeFetcher( nodes: result, }; - api.dispatch({ - type: 'serverReturnedResolverData', - payload: { - result: resolverTree, - dataSource, + if (resolverTree.nodes.length === 0) { + const unboundedTree = await dataAccessLayer.resolverTree({ + dataId: entityIDToFetch, schema: dataSourceSchema, - parameters: databaseParameters, - }, - }); + indices: databaseParameters.indices, + ancestors: ancestorsRequestAmount(dataSourceSchema), + descendants: descendantsRequestAmount(), + }); + if (unboundedTree.length > 0) { + const timestamps = unboundedTree.map((event) => + firstNonNullValue(event.data['@timestamp']) + ); + const oldestTimestamp = timestamps[0]; + const newestTimestamp = timestamps.slice(-1); + api.dispatch({ + type: 'serverReturnedResolverData', + payload: { + result: { ...resolverTree, nodes: unboundedTree }, + dataSource, + schema: dataSourceSchema, + parameters: databaseParameters, + detectedBounds: { + from: String(oldestTimestamp), + to: String(newestTimestamp), + }, + }, + }); + // 0 results with unbounded query, fail as before + } else { + api.dispatch({ + type: 'serverReturnedResolverData', + payload: { + result: resolverTree, + dataSource, + schema: dataSourceSchema, + parameters: databaseParameters, + }, + }); + } + } else { + api.dispatch({ + type: 'serverReturnedResolverData', + payload: { + result: resolverTree, + dataSource, + schema: dataSourceSchema, + parameters: databaseParameters, + }, + }); + } } catch (error) { // https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-AbortError if (error instanceof DOMException && error.name === 'AbortError') { diff --git a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts index 1940e680e1b56..8d19d49745230 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts @@ -30,6 +30,8 @@ export const projectionMatrix = composeSelectors( export const translation = composeSelectors(cameraStateSelector, cameraSelectors.translation); +export const detectedBounds = composeSelectors(dataStateSelector, dataSelectors.detectedBounds); + /** * A matrix that when applied to a Vector2 converts it from screen coordinates to world coordinates. * See https://en.wikipedia.org/wiki/Orthographic_projection diff --git a/x-pack/plugins/security_solution/public/resolver/types.ts b/x-pack/plugins/security_solution/public/resolver/types.ts index d0f63ff522438..00ecd995176eb 100644 --- a/x-pack/plugins/security_solution/public/resolver/types.ts +++ b/x-pack/plugins/security_solution/public/resolver/types.ts @@ -307,6 +307,8 @@ export interface DataState { data: SafeResolverEvent | null; }; + readonly detectedBounds?: TimeFilters; + readonly tree?: { /** * The parameters passed from the resolver properties @@ -670,8 +672,8 @@ export interface IsometricTaxiLayout { * Defines the type for bounding a search by a time box. */ export interface TimeRange { - from: string; - to: string; + from: string | number; + to: string | number; } /** @@ -762,7 +764,7 @@ export interface DataAccessLayer { }: { dataId: string; schema: ResolverSchema; - timeRange: TimeRange; + timeRange?: TimeRange; indices: string[]; ancestors: number; descendants: number; diff --git a/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx b/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx index 91c2527265361..f10864cf228f7 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/resolver_without_providers.tsx @@ -27,6 +27,7 @@ import { PanelRouter } from './panels'; import { useColors } from './use_colors'; import { useSyncSelectedNode } from './use_sync_selected_node'; import { ResolverNoProcessEvents } from './resolver_no_process_events'; +import { useAutotuneTimerange } from './use_autotune_timerange'; /** * The highest level connected Resolver component. Needs a `Provider` in its ancestry to work. @@ -58,7 +59,7 @@ export const ResolverWithoutProviders = React.memo( shouldUpdate, filters, }); - + useAutotuneTimerange(); /** * This will keep the selectedNode in the view in sync with the nodeID specified in the url */ diff --git a/x-pack/plugins/security_solution/public/resolver/view/use_autotune_timerange.ts b/x-pack/plugins/security_solution/public/resolver/view/use_autotune_timerange.ts new file mode 100644 index 0000000000000..7ecaf5dfbcbdb --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/view/use_autotune_timerange.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 { useMemo, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useSelector } from 'react-redux'; +import * as selectors from '../store/selectors'; +import { useAppToasts } from '../../common/hooks/use_app_toasts'; +import { useFormattedDate } from './panels/use_formatted_date'; +import type { ResolverState } from '../types'; + +export function useAutotuneTimerange() { + const { addSuccess } = useAppToasts(); + const { from: detectedFrom, to: detectedTo } = useSelector((state: ResolverState) => { + const detectedBounds = selectors.detectedBounds(state); + return { + from: detectedBounds?.from ? detectedBounds.from : undefined, + to: detectedBounds?.to ? detectedBounds.to : undefined, + }; + }); + const detectedFormattedFrom = useFormattedDate(detectedFrom); + const detectedFormattedTo = useFormattedDate(detectedTo); + + const successMessage = useMemo(() => { + return i18n.translate('xpack.securitySolution.resolver.unboundedRequest.toast', { + defaultMessage: `No process events were found with your selected time range, however they were + found using a start date of {from} and an end date of {to}. Select a different time range in + the date picker to use a different range.`, + values: { + from: detectedFormattedFrom, + to: detectedFormattedTo, + }, + }); + }, [detectedFormattedFrom, detectedFormattedTo]); + useEffect(() => { + if (detectedFrom || detectedTo) { + addSuccess(successMessage); + } + }, [addSuccess, successMessage, detectedFrom, detectedTo]); +} diff --git a/x-pack/plugins/security_solution/public/users/pages/details/index.tsx b/x-pack/plugins/security_solution/public/users/pages/details/index.tsx index a3cb81a7d4a5b..4e2c093803096 100644 --- a/x-pack/plugins/security_solution/public/users/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/users/pages/details/index.tsx @@ -5,13 +5,23 @@ * 2.0. */ -import { EuiSpacer, EuiWindowEvent } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiSpacer, + EuiWindowEvent, +} from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; -import type { Filter } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; +import type { Filter } from '@kbn/es-query'; + +import { AlertsByStatus } from '../../../overview/components/detection_response/alerts_by_status'; +import { useSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_signal_index'; +import { AlertCountByRuleByStatus } from '../../../common/components/alert_count_by_status'; import { InputsModelId } from '../../../common/store/inputs/constants'; import { SecurityPageName } from '../../../app/types'; import { FiltersGlobal } from '../../../common/components/filters_global'; @@ -23,6 +33,7 @@ import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useKibana } from '../../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../../common/lib/keury'; import { inputsSelectors } from '../../../common/store'; +import { useAlertsPrivileges } from '../../../detections/containers/detection_engine/alerts/use_alerts_privileges'; import { setUsersDetailsTablesActivePageToZero } from '../../store/actions'; import { setAbsoluteRangeDatePicker } from '../../../common/store/inputs/actions'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; @@ -53,7 +64,9 @@ import { UsersType } from '../../store/model'; import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions'; import { useMlCapabilities } from '../../../common/components/ml/hooks/use_ml_capabilities'; import { LandingPageComponent } from '../../../common/components/landing_page'; + const QUERY_ID = 'UsersDetailsQueryId'; +const ES_USER_FIELD = 'user.name'; const UsersDetailsComponent: React.FC = ({ detailName, @@ -73,6 +86,10 @@ const UsersDetailsComponent: React.FC = ({ const query = useDeepEqualSelector(getGlobalQuerySelector); const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); + const { signalIndexName } = useSignalIndex(); + const { hasKibanaREAD, hasIndexRead } = useAlertsPrivileges(); + const canReadAlerts = hasKibanaREAD && hasIndexRead; + const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); const { globalFullScreen } = useGlobalFullScreen(); @@ -132,6 +149,14 @@ const UsersDetailsComponent: React.FC = ({ [dispatch] ); + const entityFilter = useMemo( + () => ({ + field: ES_USER_FIELD, + value: detailName, + }), + [detailName] + ); + return ( <> {indicesExist ? ( @@ -143,7 +168,6 @@ const UsersDetailsComponent: React.FC = ({ = ({ } title={detailName} /> + = ({ /> )} - + + {canReadAlerts && ( + <> + + + + + + + + + + + )} + = ({ isPlatinumOrTrialLicense )} /> - - Array<{ + range: { '@timestamp': { gte: string; lte: string; format: string } }; + }>; +} + +export class BaseResolverQuery implements ResolverQueryParams { + readonly schema: ResolverSchema; + readonly indexPatterns: string | string[]; + readonly timeRange: TimeRange | undefined; + readonly isInternalRequest: boolean; + readonly resolverFields?: JsonValue[]; + + constructor({ schema, indexPatterns, timeRange, isInternalRequest }: ResolverQueryParams) { + this.resolverFields = resolverFields(schema); + this.schema = schema; + this.indexPatterns = indexPatterns; + this.timeRange = timeRange; + this.isInternalRequest = isInternalRequest; + } + + getRangeFilter() { + return this.timeRange + ? [ + { + range: { + '@timestamp': { + gte: this.timeRange.from, + lte: this.timeRange.to, + format: 'strict_date_optional_time', + }, + }, + }, + ] + : []; + } +} diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts index 650549b9a9c49..daa3a513821d1 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts @@ -8,32 +8,20 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { IScopedClusterClient } from '@kbn/core/server'; import type { JsonObject, JsonValue } from '@kbn/utility-types'; -import type { FieldsObject, ResolverSchema } from '../../../../../../common/endpoint/types'; -import type { NodeID, TimeRange } from '../utils'; -import { resolverFields, validIDs } from '../utils'; -interface DescendantsParams { - schema: ResolverSchema; - indexPatterns: string | string[]; - timeRange: TimeRange; - isInternalRequest: boolean; -} +import type { FieldsObject } from '../../../../../../common/endpoint/types'; +import type { NodeID } from '../utils'; +import { validIDs } from '../utils'; +import type { ResolverQueryParams } from './base'; +import { BaseResolverQuery } from './base'; /** * Builds a query for retrieving descendants of a node. */ -export class DescendantsQuery { - private readonly schema: ResolverSchema; - private readonly indexPatterns: string | string[]; - private readonly timeRange: TimeRange; - private readonly isInternalRequest: boolean; - private readonly resolverFields: JsonValue[]; +export class DescendantsQuery extends BaseResolverQuery { + declare readonly resolverFields: JsonValue[]; - constructor({ schema, indexPatterns, timeRange, isInternalRequest }: DescendantsParams) { - this.resolverFields = resolverFields(schema); - this.schema = schema; - this.indexPatterns = indexPatterns; - this.timeRange = timeRange; - this.isInternalRequest = isInternalRequest; + constructor({ schema, indexPatterns, timeRange, isInternalRequest }: ResolverQueryParams) { + super({ schema, indexPatterns, timeRange, isInternalRequest }); } private query(nodes: NodeID[], size: number): JsonObject { @@ -48,15 +36,7 @@ export class DescendantsQuery { query: { bool: { filter: [ - { - range: { - '@timestamp': { - gte: this.timeRange.from, - lte: this.timeRange.to, - format: 'strict_date_optional_time', - }, - }, - }, + ...this.getRangeFilter(), { terms: { [this.schema.parent]: nodes }, }, @@ -135,15 +115,7 @@ export class DescendantsQuery { query: { bool: { filter: [ - { - range: { - '@timestamp': { - gte: this.timeRange.from, - lte: this.timeRange.to, - format: 'strict_date_optional_time', - }, - }, - }, + ...this.getRangeFilter(), { terms: { [ancestryField]: nodes, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/lifecycle.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/lifecycle.ts index 039867c9760f7..26f917a3008d2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/lifecycle.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/lifecycle.ts @@ -7,32 +7,19 @@ import type { IScopedClusterClient } from '@kbn/core/server'; import type { JsonObject, JsonValue } from '@kbn/utility-types'; -import type { FieldsObject, ResolverSchema } from '../../../../../../common/endpoint/types'; -import type { NodeID, TimeRange } from '../utils'; -import { validIDs, resolverFields } from '../utils'; - -interface LifecycleParams { - schema: ResolverSchema; - indexPatterns: string | string[]; - timeRange: TimeRange; - isInternalRequest: boolean; -} +import type { FieldsObject } from '../../../../../../common/endpoint/types'; +import type { NodeID } from '../utils'; +import { validIDs } from '../utils'; +import type { ResolverQueryParams } from './base'; +import { BaseResolverQuery } from './base'; /** * Builds a query for retrieving descendants of a node. */ -export class LifecycleQuery { - private readonly schema: ResolverSchema; - private readonly indexPatterns: string | string[]; - private readonly timeRange: TimeRange; - private readonly isInternalRequest: boolean; - private readonly resolverFields: JsonValue[]; - constructor({ schema, indexPatterns, timeRange, isInternalRequest }: LifecycleParams) { - this.resolverFields = resolverFields(schema); - this.schema = schema; - this.indexPatterns = indexPatterns; - this.timeRange = timeRange; - this.isInternalRequest = isInternalRequest; +export class LifecycleQuery extends BaseResolverQuery { + declare readonly resolverFields: JsonValue[]; + constructor({ schema, indexPatterns, timeRange, isInternalRequest }: ResolverQueryParams) { + super({ schema, indexPatterns, timeRange, isInternalRequest }); } private query(nodes: NodeID[]): JsonObject { @@ -47,15 +34,7 @@ export class LifecycleQuery { query: { bool: { filter: [ - { - range: { - '@timestamp': { - gte: this.timeRange.from, - lte: this.timeRange.to, - format: 'strict_date_optional_time', - }, - }, - }, + ...this.getRangeFilter(), { terms: { [this.schema.id]: nodes }, }, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/stats.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/stats.ts index eb06b7b6f5f5e..38986126f7051 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/stats.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/stats.ts @@ -8,8 +8,10 @@ import type { IScopedClusterClient } from '@kbn/core/server'; import type { AlertsClient } from '@kbn/rule-registry-plugin/server'; import type { JsonObject } from '@kbn/utility-types'; -import type { EventStats, ResolverSchema } from '../../../../../../common/endpoint/types'; -import type { NodeID, TimeRange } from '../utils'; +import type { EventStats } from '../../../../../../common/endpoint/types'; +import type { NodeID } from '../utils'; +import type { ResolverQueryParams } from './base'; +import { BaseResolverQuery } from './base'; interface AggBucket { key: string; @@ -26,27 +28,12 @@ interface CategoriesAgg extends AggBucket { }; } -interface StatsParams { - schema: ResolverSchema; - indexPatterns: string | string[]; - timeRange: TimeRange; - isInternalRequest: boolean; -} - /** * Builds a query for retrieving descendants of a node. */ -export class StatsQuery { - private readonly schema: ResolverSchema; - private readonly indexPatterns: string | string[]; - private readonly timeRange: TimeRange; - private readonly isInternalRequest: boolean; - - constructor({ schema, indexPatterns, timeRange, isInternalRequest }: StatsParams) { - this.schema = schema; - this.indexPatterns = indexPatterns; - this.timeRange = timeRange; - this.isInternalRequest = isInternalRequest; +export class StatsQuery extends BaseResolverQuery { + constructor({ schema, indexPatterns, timeRange, isInternalRequest }: ResolverQueryParams) { + super({ schema, indexPatterns, timeRange, isInternalRequest }); } private query(nodes: NodeID[]): JsonObject { @@ -55,15 +42,7 @@ export class StatsQuery { query: { bool: { filter: [ - { - range: { - '@timestamp': { - gte: this.timeRange.from, - lte: this.timeRange.to, - format: 'strict_date_optional_time', - }, - }, - }, + ...this.getRangeFilter(), { terms: { [this.schema.id]: nodes }, }, @@ -105,15 +84,7 @@ export class StatsQuery { query: { bool: { filter: [ - { - range: { - '@timestamp': { - gte: this.timeRange.from, - lte: this.timeRange.to, - format: 'strict_date_optional_time', - }, - }, - }, + ...this.getRangeFilter(), { terms: { [this.schema.id]: nodes }, }, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/utils/fetch.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/utils/fetch.ts index 148371cac74ab..85b5bbd8a277d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/utils/fetch.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/utils/fetch.ts @@ -30,7 +30,7 @@ export interface TreeOptions { descendantLevels: number; descendants: number; ancestors: number; - timeRange: { + timeRange?: { from: string; to: string; }; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts index aa5e45d3d66e6..eb53a6a4338a8 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts @@ -205,9 +205,10 @@ const getActionDetailsList = async ({ throw err; } - if (!actionRequests?.body?.hits?.hits) + if (!actionRequests?.body?.hits?.hits) { // return empty details array return { actionDetails: [], totalRecords: 0 }; + } // format endpoint actions into { type, item } structure const formattedActionRequests = formatEndpointActionResults(actionRequests?.body?.hits?.hits); diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts index 47b4840665e64..8ffd33e070d98 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts @@ -120,8 +120,8 @@ const getCloudPolicyWithIntegrationConfig = ( }, malware: { ...policy.linux.malware, - // Malware protection mode based on cloud settings - mode: config.cloudConfig.preventions.malware ? ProtectionModes.prevent : ProtectionModes.off, + // Disabling Malware protection, since it's not supported on Cloud integrations due to performance reasons + mode: ProtectionModes.off, }, behavior_protection: { ...policy.linux.behavior_protection, diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts index d56dd6a02d4cd..76bd3e8af93fb 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts @@ -48,7 +48,7 @@ const validateEndpointIntegrationConfig = ( const validateCloudIntegrationConfig = (config: PolicyCreateCloudConfig, logger: Logger): void => { if (!config?.cloudConfig?.preventions) { logger.warn( - 'missing cloudConfig preventions: {preventions : malware: true / false, behavior_protection: true / false}' + 'missing cloudConfig preventions: {preventions : behavior_protection: true / false}' ); throwError('invalid value for cloudConfig: missing preventions '); } @@ -58,12 +58,6 @@ const validateCloudIntegrationConfig = (config: PolicyCreateCloudConfig, logger: ); throwError('invalid value for cloudConfig preventions behavior_protection'); } - if (typeof config.cloudConfig.preventions.malware !== 'boolean') { - logger.warn( - `invalid value for cloudConfig preventions malware: ${config.cloudConfig.preventions.malware}` - ); - throwError('invalid value for cloudConfig preventions malware'); - } if (!config?.eventFilters) { logger.warn( `eventFilters is required for cloud integration: {eventFilters : nonInteractiveSession: true / false}` diff --git a/x-pack/plugins/session_view/public/components/session_view/index.test.tsx b/x-pack/plugins/session_view/public/components/session_view/index.test.tsx index ccda24a88c559..e4650ca2eb4f1 100644 --- a/x-pack/plugins/session_view/public/components/session_view/index.test.tsx +++ b/x-pack/plugins/session_view/public/components/session_view/index.test.tsx @@ -189,7 +189,7 @@ describe('SessionView component', () => { }); }); - it('should NOT show tty player button, if session has no output', async () => { + it('should show tty player button as disabled, if session has no output', async () => { mockedApi.mockImplementation(async (options) => { // for some reason the typescript interface for options says its an object with a field called path. // in reality options is a string (which equals the path...) @@ -207,7 +207,9 @@ describe('SessionView component', () => { render(); await waitFor(() => { - expect(renderResult.queryByTestId('sessionView:TTYPlayerToggle')).toBeFalsy(); + expect(renderResult.queryByTestId('sessionView:TTYPlayerToggle')).toHaveClass( + 'euiButtonIcon-isDisabled' + ); }); }); }); diff --git a/x-pack/plugins/session_view/public/components/session_view/index.tsx b/x-pack/plugins/session_view/public/components/session_view/index.tsx index 01f072f5c52b5..32cc5dffdea5d 100644 --- a/x-pack/plugins/session_view/public/components/session_view/index.tsx +++ b/x-pack/plugins/session_view/public/components/session_view/index.tsx @@ -13,12 +13,12 @@ import { EuiPanel, EuiHorizontalRule, EuiFlexGroup, - EuiBetaBadge, EuiButtonIcon, EuiToolTip, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import useLocalStorage from 'react-use/lib/useLocalStorage'; +import byteSize from 'byte-size'; import { SectionLoading } from '../../shared_imports'; import { ProcessTree } from '../process_tree'; import { @@ -40,7 +40,7 @@ import { useFetchGetTotalIOBytes, } from './hooks'; import { LOCAL_STORAGE_DISPLAY_OPTIONS_KEY } from '../../../common/constants'; -import { BETA, REFRESH_SESSION, TOGGLE_TTY_PLAYER, DETAIL_PANEL } from './translations'; +import { REFRESH_SESSION, TOGGLE_TTY_PLAYER, DETAIL_PANEL } from './translations'; /** * The main wrapper component for the session view. @@ -142,6 +142,11 @@ export const SessionView = ({ const { data: totalTTYOutputBytes, refetch: refetchTotalTTYOutput } = useFetchGetTotalIOBytes(sessionEntityId); const hasTTYOutput = !!totalTTYOutputBytes?.total; + const bytesOfOutput = useMemo(() => { + const { unit, value } = byteSize(totalTTYOutputBytes?.total || 0); + + return { unit, value }; + }, [totalTTYOutputBytes?.total]); const handleRefresh = useCallback(() => { refetch({ refetchPage: (_page, index, allPages) => allPages.length - 1 === index }); @@ -259,9 +264,6 @@ export const SessionView = ({
- - - - {hasTTYOutput && ( - - + + {bytesOfOutput.value} {bytesOfOutput.unit} - } - > - - - - )} + + } + > + + + { const { euiTheme, euiVars } = useEuiTheme(); const cached = useMemo(() => { - const { border, colors, size } = euiTheme; + const { border, size } = euiTheme; // 118px = Session View Toolbar height + Close Session button height + spacing margin at the bottom const sessionView: CSSObject = { @@ -55,17 +55,12 @@ export const useStyles = ({ height = 500, isFullScreen }: StylesDeps) => { }, }; - const betaBadge: CSSObject = { - backgroundColor: `${colors.emptyShade}`, - }; - return { processTree, detailPanel, nonGrowGroup, resizeHandle, sessionViewerComponent, - betaBadge, }; }, [euiTheme, isFullScreen, height, euiVars]); diff --git a/x-pack/plugins/session_view/public/components/tty_player/index.tsx b/x-pack/plugins/session_view/public/components/tty_player/index.tsx index bb93e6f0dddcf..394ade4a5439e 100644 --- a/x-pack/plugins/session_view/public/components/tty_player/index.tsx +++ b/x-pack/plugins/session_view/public/components/tty_player/index.tsx @@ -5,7 +5,14 @@ * 2.0. */ import React, { useRef, useState, useCallback, useMemo, useEffect } from 'react'; -import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiButtonIcon, EuiButton } from '@elastic/eui'; +import { + EuiPanel, + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiButton, + EuiBetaBadge, +} from '@elastic/eui'; import { throttle } from 'lodash'; import { ProcessEvent } from '../../../common/types/process_tree'; import { TTYSearchBar } from '../tty_search_bar'; @@ -18,7 +25,7 @@ import { } from '../../../common/constants'; import { useFetchIOEvents, useIOLines, useXtermPlayer } from './hooks'; import { TTYPlayerControls } from '../tty_player_controls'; -import { TOGGLE_TTY_PLAYER, DETAIL_PANEL } from '../session_view/translations'; +import { BETA, TOGGLE_TTY_PLAYER, DETAIL_PANEL } from '../session_view/translations'; export interface TTYPlayerDeps { show: boolean; @@ -115,6 +122,9 @@ export const TTYPlayer = ({
+ + + diff --git a/x-pack/plugins/session_view/public/components/tty_player/styles.ts b/x-pack/plugins/session_view/public/components/tty_player/styles.ts index 34c68a8a94fae..801dd59a11a0c 100644 --- a/x-pack/plugins/session_view/public/components/tty_player/styles.ts +++ b/x-pack/plugins/session_view/public/components/tty_player/styles.ts @@ -38,6 +38,7 @@ export const useStyles = (tty?: Teletype, show?: boolean) => { }; const header: CSSObject = { + display: show ? 'block' : 'none', backgroundColor: `${euiVars.euiFormBackgroundDisabledColor}`, padding: `${size.m} ${size.base}`, }; @@ -73,18 +74,23 @@ export const useStyles = (tty?: Teletype, show?: boolean) => { const scrollPane: CSSObject = { position: 'relative', transform: `translateY(${show ? 0 : '100%'})`, - transition: 'transform .2s', + transition: 'transform .2s ease-in-out', width: '100%', - height: 'calc(100% - 120px)', + height: 'calc(100% - 112px)', overflow: 'auto', backgroundColor: colors.ink, }; + const betaBadge: CSSObject = { + backgroundColor: `${colors.emptyShade}`, + }; + return { container, header, terminal, scrollPane, + betaBadge, }; }, [euiTheme, show, euiVars.euiFormBackgroundDisabledColor, tty?.rows, tty?.columns]); diff --git a/x-pack/plugins/session_view/public/components/tty_player_controls/index.tsx b/x-pack/plugins/session_view/public/components/tty_player_controls/index.tsx index fffb7493f4c9e..58709d92772f7 100644 --- a/x-pack/plugins/session_view/public/components/tty_player_controls/index.tsx +++ b/x-pack/plugins/session_view/public/components/tty_player_controls/index.tsx @@ -12,6 +12,7 @@ import { EuiFlexItem, EuiButtonIcon, EuiToolTip, + EuiButtonIconProps, } from '@elastic/eui'; import { findIndex } from 'lodash'; import { ProcessStartMarker, ProcessEvent } from '../../../common/types/process_tree'; @@ -54,6 +55,13 @@ export const TTYPlayerControls = ({ }: TTYPlayerControlsDeps) => { const styles = useStyles(); + const commonButtonProps: Partial = { + display: 'empty', + size: 's', + color: 'ghost', + css: styles.controlButton, + }; + const onLineChange = useCallback( (event: ChangeEvent | MouseEvent) => { const line = parseInt((event?.target as HTMLInputElement).value || '0', 10); @@ -111,65 +119,55 @@ export const TTYPlayerControls = ({ @@ -179,6 +177,7 @@ export const TTYPlayerControls = ({ linesLength={linesLength} currentLine={currentLine} onChange={onLineChange} + onSeekLine={onSeekLine} /> @@ -188,6 +187,7 @@ export const TTYPlayerControls = ({ onClick={handleViewInSession} iconType="arrowRight" aria-label={VIEW_IN_SESSION} + color="ghost" > {VIEW_IN_SESSION} diff --git a/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/index.tsx b/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/index.tsx index 2eb0c0b3ecf88..e0d2f7b140d5f 100644 --- a/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/index.tsx +++ b/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/index.tsx @@ -6,7 +6,7 @@ */ import React, { ChangeEvent, MouseEvent, useMemo } from 'react'; -import { EuiRange } from '@elastic/eui'; +import { EuiRange, EuiToolTip } from '@elastic/eui'; import type { ProcessStartMarker } from '../../../../common/types/process_tree'; import { useStyles } from './styles'; import { PlayHead } from './play_head'; @@ -16,11 +16,13 @@ type Props = { linesLength: number; currentLine: number; onChange: (e: ChangeEvent | MouseEvent) => void; + onSeekLine(line: number): void; }; type TTYPlayerLineMarker = { line: number; type: 'output' | 'data_limited'; + name: string; }; export const TTYPlayerControlsMarkers = ({ @@ -28,8 +30,11 @@ export const TTYPlayerControlsMarkers = ({ linesLength, currentLine, onChange, + onSeekLine, }: Props) => { - const styles = useStyles(); + const progress = useMemo(() => (currentLine / linesLength) * 100, [currentLine, linesLength]); + + const styles = useStyles(progress); const markers = useMemo(() => { if (processStartMarkers.length < 1) { @@ -41,22 +46,29 @@ export const TTYPlayerControlsMarkers = ({ type: event.process?.io?.max_bytes_per_process_exceeded === true ? 'data_limited' : 'output', line, + name: event.process?.name, } as TTYPlayerLineMarker) ); }, [processStartMarkers]); const markersLength = markers.length; + + const currentSelectedType = useMemo(() => { + if (!markersLength) { + return undefined; + } + const currentSelected = + currentLine >= markers[markersLength - 1].line + ? markersLength - 1 + : markers.findIndex((marker) => marker.line > currentLine) - 1; + + return markers[Math.max(0, currentSelected)].type; + }, [currentLine, markers, markersLength]); + if (!markersLength) { return null; } - const currentSelected = - currentLine >= markers[markersLength - 1].line - ? markersLength - 1 - : markers.findIndex((marker) => marker.line > currentLine) - 1; - - const currentSelectedType = markers[Math.max(0, currentSelected)].type; - return ( <> - +
- {markers.map(({ line, type }, idx) => { + {markers.map(({ line, type, name }, idx) => { const selected = currentLine >= line && (idx === markersLength - 1 || currentLine < markers[idx + 1].line); // markers positions are absolute, setting higher z-index on the selected one in case there // are severals next to each other - const style = { - left: `${(line * 100) / linesLength}%`, + const markerWrapperPositioning = { + left: `${(line / linesLength) * 100}%`, zIndex: selected ? 3 : 2, }; + const onMarkerClick = () => onSeekLine(line); + return ( - +
+ + + +
); })}
diff --git a/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts b/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts index 58f6d2b01afa6..b9af9f4ec0331 100644 --- a/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts +++ b/x-pack/plugins/session_view/public/components/tty_player_controls/tty_player_controls_markers/styles.ts @@ -11,7 +11,7 @@ import { useEuiTheme } from '../../../hooks'; type TTYPlayerLineMarkerType = 'output' | 'data_limited'; -export const useStyles = () => { +export const useStyles = (progress: number) => { const { euiTheme, euiVars } = useEuiTheme(); const cached = useMemo(() => { const { border } = euiTheme; @@ -23,6 +23,12 @@ export const useStyles = () => { width: '100%', }; + const markerWrapper: CSSObject = { + position: 'absolute', + top: 0, + lineHeight: 0, + }; + const getMarkerBackgroundColor = (type: TTYPlayerLineMarkerType, selected: boolean) => { if (type === 'data_limited') { return euiVars.terminalOutputMarkerWarning; @@ -36,7 +42,6 @@ export const useStyles = () => { const marker = (type: TTYPlayerLineMarkerType, selected: boolean): CSSObject => ({ fontSize: 0, overflow: 'hidden', - position: 'absolute', padding: 0, width: 3, height: 12, @@ -44,10 +49,8 @@ export const useStyles = () => { border: `${border.width.thick} solid ${euiVars.terminalOutputBackground}`, borderRadius: border.radius.small, boxSizing: 'content-box', - top: 0, - pointerEvents: 'none', marginLeft: '-3.5px', - transition: 'left .5s ease-in-out .3s', + transition: 'left .5s ease-in-out', }); const playHeadThumb: CSSObject = { @@ -82,6 +85,9 @@ export const useStyles = () => { "input[type='range']::-moz-range-thumb": customThumb, '.euiRangeHighlight__progress': { backgroundColor: euiVars.euiColorVis0_behindText, + width: progress + '%', + borderBottomRightRadius: 0, + borderTopRightRadius: 0, }, '.euiRangeSlider:focus ~ .euiRangeHighlight .euiRangeHighlight__progress': { backgroundColor: euiVars.euiColorVis0_behindText, @@ -93,9 +99,10 @@ export const useStyles = () => { }, }; - const playHead = (type: TTYPlayerLineMarkerType): CSSObject => ({ + const playHead = (type?: TTYPlayerLineMarkerType): CSSObject => ({ ...playHeadThumb, position: 'absolute', + left: progress + '%', top: 16, fill: type === 'data_limited' @@ -105,11 +112,21 @@ export const useStyles = () => { return { marker, + markerWrapper, markersOverlay, range, playHead, }; - }, [euiTheme, euiVars]); + }, [ + euiTheme, + euiVars.euiColorVis0_behindText, + euiVars.euiColorVis1, + euiVars.terminalOutputBackground, + euiVars.terminalOutputMarkerAccent, + euiVars.terminalOutputMarkerWarning, + euiVars.terminalOutputSliderBackground, + progress, + ]); return cached; }; diff --git a/x-pack/plugins/session_view/public/components/tty_text_sizer/index.tsx b/x-pack/plugins/session_view/public/components/tty_text_sizer/index.tsx index 44c4f6801d3ba..42531fc7f5e6c 100644 --- a/x-pack/plugins/session_view/public/components/tty_text_sizer/index.tsx +++ b/x-pack/plugins/session_view/public/components/tty_text_sizer/index.tsx @@ -5,7 +5,13 @@ * 2.0. */ import React, { useCallback, useEffect, useState } from 'react'; -import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { + EuiButtonIcon, + EuiButtonIconProps, + EuiFlexGroup, + EuiFlexItem, + EuiToolTip, +} from '@elastic/eui'; import { Teletype } from '../../../common/types/process_tree'; import { DEFAULT_TTY_FONT_SIZE } from '../../../common/constants'; import { ZOOM_IN, ZOOM_FIT, ZOOM_OUT } from './translations'; @@ -19,6 +25,12 @@ export interface TTYTextSizerDeps { onFontSizeChanged(newSize: number): void; } +const commonButtonProps: Partial = { + display: 'empty', + size: 's', + color: 'ghost', +}; + const LINE_HEIGHT_SCALE_RATIO = 1.3; const MINIMUM_FONT_SIZE = 2; const MAXIMUM_FONT_SIZE = 20; @@ -88,6 +100,7 @@ export const TTYTextSizer = ({ display={fit ? 'fill' : 'empty'} iconType={fit ? 'expand' : 'minimize'} onClick={onToggleFit} + {...commonButtonProps} />
@@ -95,12 +108,13 @@ export const TTYTextSizer = ({
- + @@ -108,12 +122,13 @@ export const TTYTextSizer = ({ {`${Math.round((fontSize / DEFAULT_TTY_FONT_SIZE) * 100)}%`} - + diff --git a/x-pack/plugins/session_view/public/components/tty_text_sizer/styles.ts b/x-pack/plugins/session_view/public/components/tty_text_sizer/styles.ts index d233626c1de66..7cc47374f5434 100644 --- a/x-pack/plugins/session_view/public/components/tty_text_sizer/styles.ts +++ b/x-pack/plugins/session_view/public/components/tty_text_sizer/styles.ts @@ -16,14 +16,13 @@ export const useStyles = () => { const ratio: CSSObject = { fontSize: size.m, + color: colors.ghost, }; const separator: CSSObject = { background: colors.lightShade, height: size.xl, width: border.width.thin, - marginLeft: size.xs, - marginRight: size.xs, }; return { diff --git a/x-pack/plugins/session_view/public/components/tty_text_sizer/translations.ts b/x-pack/plugins/session_view/public/components/tty_text_sizer/translations.ts index 0bec7775d43c5..96e5d9d006dea 100644 --- a/x-pack/plugins/session_view/public/components/tty_text_sizer/translations.ts +++ b/x-pack/plugins/session_view/public/components/tty_text_sizer/translations.ts @@ -11,7 +11,7 @@ export const ZOOM_IN = i18n.translate('xpack.sessionView.zoomIn', { }); export const ZOOM_FIT = i18n.translate('xpack.sessionView.zoomFit', { - defaultMessage: 'Zoom fit', + defaultMessage: 'Fit screen', }); export const ZOOM_OUT = i18n.translate('xpack.sessionView.zoomOut', { diff --git a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts index 0060039f6f2ca..70a8628246b71 100644 --- a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts +++ b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts @@ -586,6 +586,41 @@ const ERROR_NAMESPACE_SPECIFIED = 'Spaces currently determines the namespaces'; }); }); + describe('#bulkDelete', () => { + test(`throws error if options.namespace is specified`, async () => { + const { client } = createSpacesSavedObjectsClient(); + + await expect( + // @ts-expect-error + client.bulkDelete(null, { namespace: 'bar' }) + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); + }); + + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = createSpacesSavedObjectsClient(); + const expectedReturnValue = { statuses: [{ id: 'id', type: 'type', success: true }] }; + baseClient.bulkDelete.mockReturnValue(Promise.resolve(expectedReturnValue)); + + const actualReturnValue = await client.bulkDelete([{ id: 'id', type: 'foo' }], { + force: true, + }); + + expect(actualReturnValue).toBe(expectedReturnValue); + expect(baseClient.bulkDelete).toHaveBeenCalledWith( + [ + { + id: 'id', + type: 'foo', + }, + ], + { + namespace: currentSpace.expectedNamespace, + force: true, + } + ); + }); + }); + describe('#removeReferencesTo', () => { test(`throws error if options.namespace is specified`, async () => { const { client } = createSpacesSavedObjectsClient(); diff --git a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts index a7ef2dae5b386..52ca1f2604e88 100644 --- a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts +++ b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts @@ -12,6 +12,8 @@ import type { SavedObject, SavedObjectsBaseOptions, SavedObjectsBulkCreateObject, + SavedObjectsBulkDeleteObject, + SavedObjectsBulkDeleteOptions, SavedObjectsBulkGetObject, SavedObjectsBulkResolveObject, SavedObjectsBulkUpdateObject, @@ -139,6 +141,17 @@ export class SpacesSavedObjectsClient implements SavedObjectsClientContract { }); } + async bulkDelete( + objects: SavedObjectsBulkDeleteObject[] = [], + options: SavedObjectsBulkDeleteOptions = {} + ) { + throwErrorIfNamespaceSpecified(options); + return await this.client.bulkDelete(objects, { + ...options, + namespace: spaceIdToNamespace(this.spaceId), + }); + } + async find(options: SavedObjectsFindOptions) { let namespaces: string[]; try { diff --git a/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts b/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts index 70b494a42f121..1d142bbe33c68 100644 --- a/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts +++ b/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts @@ -46,6 +46,7 @@ export const DEFAULT_COMMON_FIELDS: CommonFields = { [ConfigKey.LOCATIONS]: [], [ConfigKey.NAMESPACE]: DEFAULT_NAMESPACE_STRING, [ConfigKey.MONITOR_SOURCE_TYPE]: SourceType.UI, + [ConfigKey.JOURNEY_ID]: '', }; export const DEFAULT_BROWSER_ADVANCED_FIELDS: BrowserAdvancedFields = { @@ -63,7 +64,6 @@ export const DEFAULT_BROWSER_ADVANCED_FIELDS: BrowserAdvancedFields = { export const DEFAULT_BROWSER_SIMPLE_FIELDS: BrowserSimpleFields = { ...DEFAULT_COMMON_FIELDS, - [ConfigKey.JOURNEY_ID]: '', [ConfigKey.PROJECT_ID]: '', [ConfigKey.PLAYWRIGHT_OPTIONS]: '', [ConfigKey.METADATA]: { @@ -96,6 +96,7 @@ export const DEFAULT_BROWSER_SIMPLE_FIELDS: BrowserSimpleFields = { [ConfigKey.ZIP_URL_TLS_VERSION]: undefined, [ConfigKey.URLS]: '', [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.MULTISTEP, + [ConfigKey.TIMEOUT]: null, }; export const DEFAULT_HTTP_SIMPLE_FIELDS: HTTPSimpleFields = { diff --git a/x-pack/plugins/synthetics/common/formatters/browser/formatters.ts b/x-pack/plugins/synthetics/common/formatters/browser/formatters.ts index 1524e646bb508..f05003f650deb 100644 --- a/x-pack/plugins/synthetics/common/formatters/browser/formatters.ts +++ b/x-pack/plugins/synthetics/common/formatters/browser/formatters.ts @@ -72,7 +72,6 @@ export const browserFormatters: BrowserFormatMap = { arrayToJsonFormatter(fields[ConfigKey.JOURNEY_FILTERS_TAGS]), [ConfigKey.THROTTLING_CONFIG]: throttlingFormatter, [ConfigKey.IGNORE_HTTPS_ERRORS]: null, - [ConfigKey.JOURNEY_ID]: null, [ConfigKey.PROJECT_ID]: null, [ConfigKey.PLAYWRIGHT_OPTIONS]: null, [ConfigKey.CUSTOM_HEARTBEAT_ID]: null, diff --git a/x-pack/plugins/synthetics/common/formatters/common/formatters.ts b/x-pack/plugins/synthetics/common/formatters/common/formatters.ts index 5a5fbb864ecb3..89bf8793302ba 100644 --- a/x-pack/plugins/synthetics/common/formatters/common/formatters.ts +++ b/x-pack/plugins/synthetics/common/formatters/common/formatters.ts @@ -28,6 +28,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.REVISION]: null, [ConfigKey.MONITOR_SOURCE_TYPE]: null, [ConfigKey.FORM_MONITOR_TYPE]: null, + [ConfigKey.JOURNEY_ID]: null, }; export const arrayToJsonFormatter = (value: string[] = []) => diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/locations.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/locations.ts index 9d5e28a29a6fc..9f27becbbb023 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/locations.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/locations.ts @@ -37,8 +37,8 @@ export const BandwidthLimitKeyCodec = tEnum( export type BandwidthLimitKeyType = t.TypeOf; export const LocationGeoCodec = t.interface({ - lat: t.number, - lon: t.number, + lat: t.union([t.string, t.number]), + lon: t.union([t.string, t.number]), }); export const LocationStatusCodec = tEnum('LocationStatus', LocationStatus); @@ -77,13 +77,13 @@ export const PublicLocationsCodec = t.array(PublicLocationCodec); export const MonitorServiceLocationCodec = t.intersection([ t.interface({ id: t.string, - isServiceManaged: t.boolean, }), t.partial({ label: t.string, geo: LocationGeoCodec, url: t.string, isInvalid: t.boolean, + isServiceManaged: t.boolean, }), ]); diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts index ebb5376792d70..58e3a31df8a37 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts @@ -8,11 +8,7 @@ import * as t from 'io-ts'; import { secretKeys } from '../../constants/monitor_management'; import { ConfigKey } from './config_key'; -import { - MonitorServiceLocationsCodec, - MonitorServiceLocationCodec, - ServiceLocationErrors, -} from './locations'; +import { MonitorServiceLocationCodec, ServiceLocationErrors } from './locations'; import { DataStream, DataStreamCodec, @@ -25,6 +21,7 @@ import { VerificationModeCodec, } from './monitor_configs'; import { MetadataCodec } from './monitor_meta_data'; +import { PrivateLocationCodec } from './synthetics_private_locations'; const ScheduleCodec = t.interface({ number: t.string, @@ -77,7 +74,7 @@ export const CommonFieldsCodec = t.intersection([ [ConfigKey.SCHEDULE]: ScheduleCodec, [ConfigKey.APM_SERVICE_NAME]: t.string, [ConfigKey.TAGS]: t.array(t.string), - [ConfigKey.LOCATIONS]: MonitorServiceLocationsCodec, + [ConfigKey.LOCATIONS]: t.array(t.union([MonitorServiceLocationCodec, PrivateLocationCodec])), }), t.partial({ [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorTypeCodec, @@ -85,6 +82,7 @@ export const CommonFieldsCodec = t.intersection([ [ConfigKey.REVISION]: t.number, [ConfigKey.MONITOR_SOURCE_TYPE]: SourceTypeCodec, [ConfigKey.CONFIG_ID]: t.string, + [ConfigKey.JOURNEY_ID]: t.string, }), ]); @@ -218,7 +216,6 @@ export const EncryptedBrowserSimpleFieldsCodec = t.intersection([ }), t.partial({ [ConfigKey.PLAYWRIGHT_OPTIONS]: t.string, - [ConfigKey.JOURNEY_ID]: t.string, [ConfigKey.PROJECT_ID]: t.string, [ConfigKey.ORIGINAL_SPACE]: t.string, [ConfigKey.CUSTOM_HEARTBEAT_ID]: t.string, diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts index 072455c8914c7..6abcf4b832135 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts @@ -14,19 +14,21 @@ export const ProjectMonitorThrottlingConfigCodec = t.interface({ latency: t.number, }); -export const ProjectBrowserMonitorCodec = t.intersection([ +export const ProjectMonitorCodec = t.intersection([ t.interface({ + type: t.string, id: t.string, name: t.string, schedule: t.number, - content: t.string, locations: t.array(t.string), }), t.partial({ + content: t.string, + timeout: t.string, privateLocations: t.array(t.string), throttling: ProjectMonitorThrottlingConfigCodec, screenshot: ScreenshotOptionCodec, - tags: t.array(t.string), + tags: t.union([t.string, t.array(t.string)]), ignoreHTTPSErrors: t.boolean, apmServiceName: t.string, playwrightOptions: t.record(t.string, t.unknown), @@ -35,17 +37,21 @@ export const ProjectBrowserMonitorCodec = t.intersection([ }), params: t.record(t.string, t.unknown), enabled: t.boolean, + urls: t.union([t.string, t.array(t.string)]), + hosts: t.union([t.string, t.array(t.string)]), + max_redirects: t.string, + wait: t.string, }), ]); export const ProjectMonitorsRequestCodec = t.interface({ project: t.string, keep_stale: t.boolean, - monitors: t.array(ProjectBrowserMonitorCodec), + monitors: t.array(ProjectMonitorCodec), }); export type ProjectMonitorThrottlingConfig = t.TypeOf; -export type ProjectBrowserMonitor = t.TypeOf; +export type ProjectMonitor = t.TypeOf; export type ProjectMonitorsRequest = t.TypeOf; diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts index 69cd76d54db86..556f1e56ed102 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts @@ -7,18 +7,23 @@ import * as t from 'io-ts'; -export const PrivateLocationType = t.intersection([ +export const PrivateLocationCodec = t.intersection([ t.interface({ label: t.string, id: t.string, agentPolicyId: t.string, concurrentMonitors: t.number, }), - t.partial({ geo: t.interface({ lat: t.number, lon: t.number }) }), + t.partial({ + isServiceManaged: t.boolean, + /* Empty Lat lon was accidentally saved as an empty string instead of undefined or null + * Need a migration to fix */ + geo: t.interface({ lat: t.union([t.string, t.number]), lon: t.union([t.string, t.number]) }), + }), ]); export const SyntheticsPrivateLocationsType = t.type({ - locations: t.array(PrivateLocationType), + locations: t.array(PrivateLocationCodec), }); -export type PrivateLocation = t.TypeOf; +export type PrivateLocation = t.TypeOf; export type SyntheticsPrivateLocations = t.TypeOf; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx index 1cf2baf1df94f..4b4e778b87b9b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx @@ -104,6 +104,7 @@ describe('format', () => { 'check.response.status': [], enabled, form_monitor_type: 'http', + journey_id: '', locations: [ { id: 'us_central', @@ -316,6 +317,7 @@ describe('format', () => { 'check.response.status': [], enabled: true, form_monitor_type: 'http', + journey_id: '', locations: [ { id: 'us_central', diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap index 9e7b46568882b..b4486e65c5396 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/charts/__snapshots__/donut_chart.test.tsx.snap @@ -403,6 +403,8 @@ exports[`DonutChart component passes correct props without errors for valid prop "metric": Object { "background": "#FFFFFF", "barBackground": "#EDF0F5", + "border": "#EDF0F5", + "minHeight": 64, "nonFiniteText": "N/A", "text": Object { "darkColor": "#343741", diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/normalizers.ts b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/normalizers.ts index 0746f2cdae279..a8b59b16a3460 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/normalizers.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/browser/normalizers.ts @@ -107,7 +107,6 @@ export const browserNormalizers: BrowserNormalizerMap = { ConfigKey.JOURNEY_FILTERS_TAGS ), [ConfigKey.IGNORE_HTTPS_ERRORS]: getBrowserNormalizer(ConfigKey.IGNORE_HTTPS_ERRORS), - [ConfigKey.JOURNEY_ID]: getBrowserNormalizer(ConfigKey.JOURNEY_ID), [ConfigKey.PROJECT_ID]: getBrowserNormalizer(ConfigKey.PROJECT_ID), [ConfigKey.PLAYWRIGHT_OPTIONS]: getBrowserNormalizer(ConfigKey.PLAYWRIGHT_OPTIONS), [ConfigKey.CUSTOM_HEARTBEAT_ID]: getBrowserNormalizer(ConfigKey.CUSTOM_HEARTBEAT_ID), diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts index bdea46781dfd9..14fab3caeb132 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts @@ -92,4 +92,5 @@ export const commonNormalizers: CommonNormalizerMap = { [ConfigKey.REVISION]: getCommonNormalizer(ConfigKey.REVISION), [ConfigKey.MONITOR_SOURCE_TYPE]: getCommonNormalizer(ConfigKey.MONITOR_SOURCE_TYPE), [ConfigKey.FORM_MONITOR_TYPE]: getCommonNormalizer(ConfigKey.FORM_MONITOR_TYPE), + [ConfigKey.JOURNEY_ID]: getCommonNormalizer(ConfigKey.JOURNEY_ID), }; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx index b3aa4714fa664..30ea0e361580a 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { OverviewPageComponent } from './overview'; import { render } from '../lib/helper/rtl_helpers'; -describe('MonitorPage', () => { +// FLAKY: https://github.com/elastic/kibana/issues/131346 +describe.skip('MonitorPage', () => { it('renders expected elements for valid props', async () => { const { findByText, findByPlaceholderText } = render(); diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts index 8b81e34840c66..668d97a0819e3 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts @@ -6,11 +6,12 @@ */ import { schema } from '@kbn/config-schema'; import { UMServerLibs } from '../../legacy_uptime/lib/lib'; -import { ProjectBrowserMonitor } from '../../../common/runtime_types'; +import { ProjectMonitor } from '../../../common/runtime_types'; + import { SyntheticsStreamingRouteFactory } from '../../legacy_uptime/routes/types'; import { API_URLS } from '../../../common/constants'; import { getAllLocations } from '../../synthetics_service/get_all_locations'; -import { ProjectMonitorFormatter } from '../../synthetics_service/project_monitor_formatter'; +import { ProjectMonitorFormatter } from '../../synthetics_service/project_monitor/project_monitor_formatter'; export const addSyntheticsProjectMonitorRoute: SyntheticsStreamingRouteFactory = ( libs: UMServerLibs @@ -32,7 +33,7 @@ export const addSyntheticsProjectMonitorRoute: SyntheticsStreamingRouteFactory = subject, }): Promise => { try { - const monitors = (request.body?.monitors as ProjectBrowserMonitor[]) || []; + const monitors = (request.body?.monitors as ProjectMonitor[]) || []; const spaceId = server.spaces.spacesService.getSpaceId(request); const { keep_stale: keepStale, project: projectId } = request.body || {}; const { publicLocations, privateLocations } = await getAllLocations( diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts index 88ae4690dd4bd..d648722e0d5cd 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts @@ -10,8 +10,8 @@ import { formatErrors } from '@kbn/securitysolution-io-ts-utils'; import { BrowserFieldsCodec, - ProjectBrowserMonitorCodec, - ProjectBrowserMonitor, + ProjectMonitorCodec, + ProjectMonitor, ConfigKey, DataStream, DataStreamCodec, @@ -34,16 +34,18 @@ const monitorTypeToCodecMap: Record = { [DataStream.BROWSER]: BrowserFieldsCodec, }; -/** - * Validates monitor fields with respect to the relevant Codec identified by object's 'type' property. - * @param monitorFields {MonitorFields} The mixed type representing the possible monitor payload from UI. - */ -export function validateMonitor(monitorFields: MonitorFields): { +export interface ValidationResult { valid: boolean; reason: string; details: string; payload: object; -} { +} + +/** + * Validates monitor fields with respect to the relevant Codec identified by object's 'type' property. + * @param monitorFields {MonitorFields} The mixed type representing the possible monitor payload from UI. + */ +export function validateMonitor(monitorFields: MonitorFields): ValidationResult { const { [ConfigKey.MONITOR_TYPE]: monitorType } = monitorFields; const decodedType = DataStreamCodec.decode(monitorType); @@ -82,15 +84,7 @@ export function validateMonitor(monitorFields: MonitorFields): { return { valid: true, reason: '', details: '', payload: monitorFields }; } -export function validateProjectMonitor( - monitorFields: ProjectBrowserMonitor, - projectId: string -): { - valid: boolean; - reason: string; - details: string; - payload: object; -} { +export function validateProjectMonitor(monitorFields: ProjectMonitor): ValidationResult { const locationsError = monitorFields.locations && monitorFields.locations.length === 0 && @@ -98,7 +92,7 @@ export function validateProjectMonitor( ? 'Invalid value "[]" supplied to field "locations"' : ''; // Cast it to ICMPCodec to satisfy typing. During runtime, correct codec will be used to decode. - const decodedMonitor = ProjectBrowserMonitorCodec.decode(monitorFields); + const decodedMonitor = ProjectMonitorCodec.decode(monitorFields); if (isLeft(decodedMonitor)) { return { diff --git a/x-pack/plugins/synthetics/server/synthetics_service/formatters/browser.ts b/x-pack/plugins/synthetics/server/synthetics_service/formatters/browser.ts index 7e8c75a708430..9c9d24a3f58f4 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/formatters/browser.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/formatters/browser.ts @@ -66,7 +66,6 @@ export const browserFormatters: BrowserFormatMap = { [ConfigKey.JOURNEY_FILTERS_TAGS]: (fields) => arrayFormatter(fields[ConfigKey.JOURNEY_FILTERS_TAGS]), [ConfigKey.IGNORE_HTTPS_ERRORS]: null, - [ConfigKey.JOURNEY_ID]: null, [ConfigKey.PROJECT_ID]: null, [ConfigKey.PLAYWRIGHT_OPTIONS]: (fields) => stringToObjectFormatter(fields[ConfigKey.PLAYWRIGHT_OPTIONS] || ''), diff --git a/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts b/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts index 0163ee52981e5..16a0829cbb710 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts @@ -30,6 +30,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.MONITOR_SOURCE_TYPE]: (fields) => fields[ConfigKey.MONITOR_SOURCE_TYPE] || SourceType.UI, [ConfigKey.FORM_MONITOR_TYPE]: null, + [ConfigKey.JOURNEY_ID]: null, }; export const arrayFormatter = (value: string[] = []) => (value.length ? value : null); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/normalizers/browser.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/normalizers/browser.test.ts deleted file mode 100644 index 3362585a523c1..0000000000000 --- a/x-pack/plugins/synthetics/server/synthetics_service/normalizers/browser.test.ts +++ /dev/null @@ -1,267 +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 { - DataStream, - ScreenshotOption, - Locations, - LocationStatus, - ProjectBrowserMonitor, - PrivateLocation, -} from '../../../common/runtime_types'; -import { DEFAULT_FIELDS } from '../../../common/constants/monitor_defaults'; -import { normalizeProjectMonitors } from './browser'; - -describe('browser normalizers', () => { - describe('normalize push monitors', () => { - const playwrightOptions = { - headless: true, - }; - const params = { - url: 'test-url', - }; - const projectId = 'test-project-id'; - const locations: Locations = [ - { - id: 'us_central', - label: 'Test Location', - geo: { lat: 33.333, lon: 73.333 }, - url: 'test-url', - isServiceManaged: true, - status: LocationStatus.GA, - }, - { - id: 'us_east', - label: 'Test Location', - geo: { lat: 33.333, lon: 73.333 }, - url: 'test-url', - isServiceManaged: true, - status: LocationStatus.GA, - }, - ]; - const privateLocations: PrivateLocation[] = [ - { - id: 'germany', - label: 'Germany', - concurrentMonitors: 1, - agentPolicyId: 'germany', - }, - ]; - const monitors: ProjectBrowserMonitor[] = [ - { - id: 'test-id-1', - screenshot: ScreenshotOption.OFF, - name: 'test-name-1', - content: 'test content 1', - schedule: 3, - throttling: { - latency: 20, - upload: 10, - download: 5, - }, - locations: ['us_central'], - tags: ['tag1', 'tag2'], - ignoreHTTPSErrors: true, - apmServiceName: 'cart-service', - }, - { - id: 'test-id-2', - screenshot: ScreenshotOption.ON, - name: 'test-name-2', - content: 'test content 2', - schedule: 10, - throttling: { - latency: 18, - upload: 15, - download: 10, - }, - params: {}, - playwrightOptions: {}, - locations: ['us_central', 'us_east'], - tags: ['tag3', 'tag4'], - ignoreHTTPSErrors: false, - apmServiceName: 'bean-service', - }, - { - id: 'test-id-3', - screenshot: ScreenshotOption.ON, - name: 'test-name-3', - content: 'test content 3', - schedule: 10, - throttling: { - latency: 18, - upload: 15, - download: 10, - }, - params, - playwrightOptions, - locations: ['us_central', 'us_east'], - privateLocations: ['Germany'], - tags: ['tag3', 'tag4'], - ignoreHTTPSErrors: false, - apmServiceName: 'bean-service', - }, - ]; - - it('properly normalizes browser monitor', () => { - const actual = normalizeProjectMonitors({ - locations, - privateLocations, - monitors, - projectId, - namespace: 'test-space', - }); - expect(actual).toEqual([ - { - ...DEFAULT_FIELDS[DataStream.BROWSER], - journey_id: 'test-id-1', - ignore_https_errors: true, - origin: 'project', - locations: [ - { - geo: { - lat: 33.333, - lon: 73.333, - }, - id: 'us_central', - isServiceManaged: true, - label: 'Test Location', - url: 'test-url', - status: 'ga', - }, - ], - name: 'test-name-1', - schedule: { - number: '3', - unit: 'm', - }, - screenshots: 'off', - 'service.name': 'cart-service', - 'source.project.content': 'test content 1', - tags: ['tag1', 'tag2'], - 'throttling.config': '5d/10u/20l', - 'throttling.download_speed': '5', - 'throttling.is_enabled': true, - 'throttling.latency': '20', - 'throttling.upload_speed': '10', - params: '', - type: 'browser', - project_id: projectId, - namespace: 'test_space', - original_space: 'test-space', - custom_heartbeat_id: 'test-id-1-test-project-id-test-space', - timeout: null, - }, - { - ...DEFAULT_FIELDS[DataStream.BROWSER], - journey_id: 'test-id-2', - ignore_https_errors: false, - origin: 'project', - locations: [ - { - geo: { - lat: 33.333, - lon: 73.333, - }, - id: 'us_central', - isServiceManaged: true, - label: 'Test Location', - url: 'test-url', - status: 'ga', - }, - { - geo: { - lat: 33.333, - lon: 73.333, - }, - id: 'us_east', - isServiceManaged: true, - label: 'Test Location', - url: 'test-url', - status: 'ga', - }, - ], - name: 'test-name-2', - params: '', - playwright_options: '', - schedule: { - number: '10', - unit: 'm', - }, - screenshots: 'on', - 'service.name': 'bean-service', - 'source.project.content': 'test content 2', - tags: ['tag3', 'tag4'], - 'throttling.config': '10d/15u/18l', - 'throttling.download_speed': '10', - 'throttling.is_enabled': true, - 'throttling.latency': '18', - 'throttling.upload_speed': '15', - type: 'browser', - project_id: projectId, - namespace: 'test_space', - original_space: 'test-space', - custom_heartbeat_id: 'test-id-2-test-project-id-test-space', - timeout: null, - }, - { - ...DEFAULT_FIELDS[DataStream.BROWSER], - journey_id: 'test-id-3', - ignore_https_errors: false, - origin: 'project', - locations: [ - { - geo: { - lat: 33.333, - lon: 73.333, - }, - id: 'us_central', - isServiceManaged: true, - label: 'Test Location', - url: 'test-url', - status: 'ga', - }, - { - geo: { - lat: 33.333, - lon: 73.333, - }, - id: 'us_east', - isServiceManaged: true, - label: 'Test Location', - url: 'test-url', - status: 'ga', - }, - privateLocations[0], - ], - name: 'test-name-3', - params: JSON.stringify(params), - playwright_options: JSON.stringify(playwrightOptions), - schedule: { - number: '10', - unit: 'm', - }, - screenshots: 'on', - 'service.name': 'bean-service', - 'source.project.content': 'test content 3', - tags: ['tag3', 'tag4'], - 'throttling.config': '10d/15u/18l', - 'throttling.download_speed': '10', - 'throttling.is_enabled': true, - 'throttling.latency': '18', - 'throttling.upload_speed': '15', - type: 'browser', - project_id: projectId, - namespace: 'test_space', - original_space: 'test-space', - custom_heartbeat_id: 'test-id-3-test-project-id-test-space', - timeout: null, - }, - ]); - }); - }); -}); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/normalizers/browser.ts b/x-pack/plugins/synthetics/server/synthetics_service/normalizers/browser.ts deleted file mode 100644 index 3b5d684fe0f58..0000000000000 --- a/x-pack/plugins/synthetics/server/synthetics_service/normalizers/browser.ts +++ /dev/null @@ -1,157 +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 { PrivateLocation } from '../../../common/runtime_types'; -import { DEFAULT_FIELDS } from '../../../common/constants/monitor_defaults'; -import { formatKibanaNamespace } from '../../../common/formatters'; -import { - BrowserFields, - ConfigKey, - DataStream, - FormMonitorType, - Locations, - ProjectBrowserMonitor, - ScheduleUnit, - SourceType, -} from '../../../common/runtime_types/monitor_management'; - -/* Represents all of the push-monitor related fields that need to be - * normalized. Excludes fields that we do not support for push monitors - * This type ensures that contributors remember to add normalizers for push - * monitors where appropriate when new keys are added to browser montiors */ -type NormalizedPublicFields = Omit< - BrowserFields, - | ConfigKey.METADATA - | ConfigKey.SOURCE_INLINE - | ConfigKey.SOURCE_ZIP_URL - | ConfigKey.SOURCE_ZIP_USERNAME - | ConfigKey.SOURCE_ZIP_PASSWORD - | ConfigKey.SOURCE_ZIP_FOLDER - | ConfigKey.SOURCE_ZIP_PROXY_URL - | ConfigKey.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES - | ConfigKey.ZIP_URL_TLS_CERTIFICATE - | ConfigKey.ZIP_URL_TLS_KEY - | ConfigKey.ZIP_URL_TLS_KEY_PASSPHRASE - | ConfigKey.ZIP_URL_TLS_VERIFICATION_MODE - | ConfigKey.ZIP_URL_TLS_VERSION - | ConfigKey.JOURNEY_FILTERS_TAGS - | ConfigKey.SYNTHETICS_ARGS - | ConfigKey.PORT - | ConfigKey.URLS ->; - -export const normalizeProjectMonitor = ({ - locations = [], - privateLocations = [], - monitor, - projectId, - namespace, -}: { - locations: Locations; - privateLocations: PrivateLocation[]; - monitor: ProjectBrowserMonitor; - projectId: string; - namespace: string; -}): BrowserFields => { - const defaultFields = DEFAULT_FIELDS[DataStream.BROWSER]; - const normalizedFields: NormalizedPublicFields = { - [ConfigKey.MONITOR_TYPE]: DataStream.BROWSER, - [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.MULTISTEP, - [ConfigKey.MONITOR_SOURCE_TYPE]: SourceType.PROJECT, - [ConfigKey.NAME]: monitor.name || '', - [ConfigKey.SCHEDULE]: { - number: `${monitor.schedule}`, - unit: ScheduleUnit.MINUTES, - }, - [ConfigKey.PROJECT_ID]: projectId || defaultFields[ConfigKey.PROJECT_ID], - [ConfigKey.JOURNEY_ID]: monitor.id || defaultFields[ConfigKey.JOURNEY_ID], - [ConfigKey.SOURCE_PROJECT_CONTENT]: - monitor.content || defaultFields[ConfigKey.SOURCE_PROJECT_CONTENT], - [ConfigKey.LOCATIONS]: getMonitorLocations({ - monitor, - privateLocations, - publicLocations: locations, - }), - [ConfigKey.THROTTLING_CONFIG]: monitor.throttling - ? `${monitor.throttling.download}d/${monitor.throttling.upload}u/${monitor.throttling.latency}l` - : defaultFields[ConfigKey.THROTTLING_CONFIG], - [ConfigKey.DOWNLOAD_SPEED]: `${ - monitor.throttling?.download || defaultFields[ConfigKey.DOWNLOAD_SPEED] - }`, - [ConfigKey.UPLOAD_SPEED]: `${ - monitor.throttling?.upload || defaultFields[ConfigKey.UPLOAD_SPEED] - }`, - [ConfigKey.IS_THROTTLING_ENABLED]: - Boolean(monitor.throttling) || defaultFields[ConfigKey.IS_THROTTLING_ENABLED], - [ConfigKey.LATENCY]: `${monitor.throttling?.latency || defaultFields[ConfigKey.LATENCY]}`, - [ConfigKey.APM_SERVICE_NAME]: - monitor.apmServiceName || defaultFields[ConfigKey.APM_SERVICE_NAME], - [ConfigKey.IGNORE_HTTPS_ERRORS]: - monitor.ignoreHTTPSErrors || defaultFields[ConfigKey.IGNORE_HTTPS_ERRORS], - [ConfigKey.SCREENSHOTS]: monitor.screenshot || defaultFields[ConfigKey.SCREENSHOTS], - [ConfigKey.TAGS]: monitor.tags || defaultFields[ConfigKey.TAGS], - [ConfigKey.PLAYWRIGHT_OPTIONS]: Object.keys(monitor.playwrightOptions || {}).length - ? JSON.stringify(monitor.playwrightOptions) - : defaultFields[ConfigKey.PLAYWRIGHT_OPTIONS], - [ConfigKey.PARAMS]: Object.keys(monitor.params || {}).length - ? JSON.stringify(monitor.params) - : defaultFields[ConfigKey.PARAMS], - [ConfigKey.JOURNEY_FILTERS_MATCH]: - monitor.filter?.match || defaultFields[ConfigKey.JOURNEY_FILTERS_MATCH], - [ConfigKey.NAMESPACE]: formatKibanaNamespace(namespace) || defaultFields[ConfigKey.NAMESPACE], - [ConfigKey.ORIGINAL_SPACE]: namespace || defaultFields[ConfigKey.ORIGINAL_SPACE], - [ConfigKey.CUSTOM_HEARTBEAT_ID]: `${monitor.id}-${projectId}-${namespace}`, - [ConfigKey.TIMEOUT]: null, - [ConfigKey.ENABLED]: monitor.enabled ?? defaultFields[ConfigKey.ENABLED], - }; - return { - ...DEFAULT_FIELDS[DataStream.BROWSER], - ...normalizedFields, - }; -}; - -export const normalizeProjectMonitors = ({ - locations = [], - privateLocations = [], - monitors = [], - projectId, - namespace, -}: { - locations: Locations; - privateLocations: PrivateLocation[]; - monitors: ProjectBrowserMonitor[]; - projectId: string; - namespace: string; -}) => { - return monitors.map((monitor) => { - return normalizeProjectMonitor({ monitor, locations, privateLocations, projectId, namespace }); - }); -}; - -export const getMonitorLocations = ({ - privateLocations, - publicLocations, - monitor, -}: { - monitor: ProjectBrowserMonitor; - privateLocations: PrivateLocation[]; - publicLocations: Locations; -}) => { - const publicLocs = - monitor.locations?.map((id) => { - return publicLocations.find((location) => location.id === id); - }) || []; - const privateLocs = - monitor.privateLocations?.map((locationName) => { - return privateLocations.find( - (location) => location.label.toLowerCase() === locationName.toLowerCase() - ); - }) || []; - return [...publicLocs, ...privateLocs].filter( - (location) => location !== undefined - ) as BrowserFields[ConfigKey.LOCATIONS]; -}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts b/x-pack/plugins/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts index 23e2c97f2fda1..c694f2aa7567e 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/private_location/synthetics_private_location.ts @@ -7,6 +7,7 @@ import { KibanaRequest, SavedObjectsClientContract } from '@kbn/core/server'; import { NewPackagePolicy } from '@kbn/fleet-plugin/common'; import { NewPackagePolicyWithId } from '@kbn/fleet-plugin/server/services/package_policy'; +import { cloneDeep } from 'lodash'; import { formatSyntheticsPolicy } from '../../../common/formatters/format_synthetics_policy'; import { getSyntheticsPrivateLocations } from '../../legacy_uptime/lib/saved_objects/private_locations'; import { @@ -55,7 +56,7 @@ export class SyntheticsPrivateLocation { const { label: locName } = privateLocation; - const newPolicy = { ...newPolicyTemplate }; + const newPolicy = cloneDeep(newPolicyTemplate); try { newPolicy.is_managed = true; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts new file mode 100644 index 0000000000000..ed02f1037e32b --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts @@ -0,0 +1,286 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + DataStream, + ScreenshotOption, + Locations, + LocationStatus, + ProjectMonitor, + PrivateLocation, +} from '../../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; +import { normalizeProjectMonitors } from '.'; + +describe('browser normalizers', () => { + describe('normalize push monitors', () => { + const playwrightOptions = { + headless: true, + }; + const params = { + url: 'test-url', + }; + const projectId = 'test-project-id'; + const locations: Locations = [ + { + id: 'us_central', + label: 'Test Location', + geo: { lat: 33.333, lon: 73.333 }, + url: 'test-url', + isServiceManaged: true, + status: LocationStatus.GA, + }, + { + id: 'us_east', + label: 'Test Location', + geo: { lat: 33.333, lon: 73.333 }, + url: 'test-url', + isServiceManaged: true, + status: LocationStatus.GA, + }, + ]; + const privateLocations: PrivateLocation[] = [ + { + id: 'germany', + label: 'Germany', + isServiceManaged: false, + concurrentMonitors: 1, + agentPolicyId: 'germany', + }, + ]; + const monitors: ProjectMonitor[] = [ + { + id: 'test-id-1', + screenshot: ScreenshotOption.OFF, + name: 'test-name-1', + content: 'test content 1', + schedule: 3, + throttling: { + latency: 20, + upload: 10, + download: 5, + }, + locations: ['us_central'], + tags: ['tag1', 'tag2'], + ignoreHTTPSErrors: true, + apmServiceName: 'cart-service', + type: DataStream.BROWSER, + }, + { + id: 'test-id-2', + screenshot: ScreenshotOption.ON, + name: 'test-name-2', + content: 'test content 2', + schedule: 10, + throttling: { + latency: 18, + upload: 15, + download: 10, + }, + params: {}, + playwrightOptions: {}, + locations: ['us_central', 'us_east'], + tags: ['tag3', 'tag4'], + ignoreHTTPSErrors: false, + apmServiceName: 'bean-service', + type: DataStream.BROWSER, + }, + { + id: 'test-id-3', + screenshot: ScreenshotOption.ON, + name: 'test-name-3', + content: 'test content 3', + schedule: 10, + throttling: { + latency: 18, + upload: 15, + download: 10, + }, + params, + playwrightOptions, + locations: ['us_central', 'us_east'], + privateLocations: ['Germany'], + tags: ['tag3', 'tag4'], + ignoreHTTPSErrors: false, + apmServiceName: 'bean-service', + type: DataStream.BROWSER, + }, + ]; + + it('properly normalizes browser monitor', () => { + const actual = normalizeProjectMonitors({ + locations, + privateLocations, + monitors, + projectId, + namespace: 'test-space', + }); + expect(actual).toEqual([ + { + normalizedFields: { + ...DEFAULT_FIELDS[DataStream.BROWSER], + journey_id: 'test-id-1', + ignore_https_errors: true, + origin: 'project', + locations: [ + { + geo: { + lat: 33.333, + lon: 73.333, + }, + id: 'us_central', + isServiceManaged: true, + label: 'Test Location', + url: 'test-url', + status: 'ga', + }, + ], + name: 'test-name-1', + schedule: { + number: '3', + unit: 'm', + }, + screenshots: 'off', + 'service.name': 'cart-service', + 'source.project.content': 'test content 1', + tags: ['tag1', 'tag2'], + 'throttling.config': '5d/10u/20l', + 'throttling.download_speed': '5', + 'throttling.is_enabled': true, + 'throttling.latency': '20', + 'throttling.upload_speed': '10', + params: '', + type: 'browser', + project_id: projectId, + namespace: 'test_space', + original_space: 'test-space', + custom_heartbeat_id: 'test-id-1-test-project-id-test-space', + timeout: null, + }, + unsupportedKeys: [], + }, + { + normalizedFields: { + ...DEFAULT_FIELDS[DataStream.BROWSER], + journey_id: 'test-id-2', + ignore_https_errors: false, + origin: 'project', + locations: [ + { + geo: { + lat: 33.333, + lon: 73.333, + }, + id: 'us_central', + isServiceManaged: true, + label: 'Test Location', + url: 'test-url', + status: 'ga', + }, + { + geo: { + lat: 33.333, + lon: 73.333, + }, + id: 'us_east', + isServiceManaged: true, + label: 'Test Location', + url: 'test-url', + status: 'ga', + }, + ], + name: 'test-name-2', + params: '', + playwright_options: '', + schedule: { + number: '10', + unit: 'm', + }, + screenshots: 'on', + 'service.name': 'bean-service', + 'source.project.content': 'test content 2', + tags: ['tag3', 'tag4'], + 'throttling.config': '10d/15u/18l', + 'throttling.download_speed': '10', + 'throttling.is_enabled': true, + 'throttling.latency': '18', + 'throttling.upload_speed': '15', + type: 'browser', + project_id: projectId, + namespace: 'test_space', + original_space: 'test-space', + custom_heartbeat_id: 'test-id-2-test-project-id-test-space', + timeout: null, + }, + unsupportedKeys: [], + }, + { + normalizedFields: { + ...DEFAULT_FIELDS[DataStream.BROWSER], + journey_id: 'test-id-3', + ignore_https_errors: false, + origin: 'project', + locations: [ + { + geo: { + lat: 33.333, + lon: 73.333, + }, + id: 'us_central', + isServiceManaged: true, + label: 'Test Location', + url: 'test-url', + status: 'ga', + }, + { + geo: { + lat: 33.333, + lon: 73.333, + }, + id: 'us_east', + isServiceManaged: true, + label: 'Test Location', + url: 'test-url', + status: 'ga', + }, + { + id: 'germany', + isServiceManaged: false, + label: 'Germany', + agentPolicyId: 'germany', + concurrentMonitors: 1, + }, + ], + name: 'test-name-3', + params: JSON.stringify(params), + playwright_options: JSON.stringify(playwrightOptions), + schedule: { + number: '10', + unit: 'm', + }, + screenshots: 'on', + 'service.name': 'bean-service', + 'source.project.content': 'test content 3', + tags: ['tag3', 'tag4'], + 'throttling.config': '10d/15u/18l', + 'throttling.download_speed': '10', + 'throttling.is_enabled': true, + 'throttling.latency': '18', + 'throttling.upload_speed': '15', + type: 'browser', + project_id: projectId, + namespace: 'test_space', + original_space: 'test-space', + custom_heartbeat_id: 'test-id-3-test-project-id-test-space', + timeout: null, + }, + unsupportedKeys: [], + }, + ]); + }); + }); +}); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.ts new file mode 100644 index 0000000000000..aae7031435c74 --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + BrowserFields, + ConfigKey, + DataStream, + FormMonitorType, + Locations, + PrivateLocation, + ProjectMonitor, +} from '../../../../common/runtime_types'; +import { getNormalizeCommonFields, getValueInSeconds } from './common_fields'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; + +export interface NormalizedProjectProps { + locations: Locations; + privateLocations: PrivateLocation[]; + monitor: ProjectMonitor; + projectId: string; + namespace: string; +} + +export const getNormalizeBrowserFields = ({ + locations = [], + privateLocations = [], + monitor, + projectId, + namespace, +}: NormalizedProjectProps): { normalizedFields: BrowserFields; unsupportedKeys: string[] } => { + const defaultFields = DEFAULT_FIELDS[DataStream.BROWSER]; + + const commonFields = getNormalizeCommonFields({ + locations, + privateLocations, + monitor, + projectId, + namespace, + }); + + const normalizedFields = { + ...commonFields, + [ConfigKey.MONITOR_TYPE]: DataStream.BROWSER, + [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.MULTISTEP, + [ConfigKey.SOURCE_PROJECT_CONTENT]: + monitor.content || defaultFields[ConfigKey.SOURCE_PROJECT_CONTENT], + [ConfigKey.THROTTLING_CONFIG]: monitor.throttling + ? `${monitor.throttling.download}d/${monitor.throttling.upload}u/${monitor.throttling.latency}l` + : defaultFields[ConfigKey.THROTTLING_CONFIG], + [ConfigKey.DOWNLOAD_SPEED]: `${ + monitor.throttling?.download || defaultFields[ConfigKey.DOWNLOAD_SPEED] + }`, + [ConfigKey.UPLOAD_SPEED]: `${ + monitor.throttling?.upload || defaultFields[ConfigKey.UPLOAD_SPEED] + }`, + [ConfigKey.IS_THROTTLING_ENABLED]: + Boolean(monitor.throttling) || defaultFields[ConfigKey.IS_THROTTLING_ENABLED], + [ConfigKey.LATENCY]: `${monitor.throttling?.latency || defaultFields[ConfigKey.LATENCY]}`, + [ConfigKey.IGNORE_HTTPS_ERRORS]: + monitor.ignoreHTTPSErrors || defaultFields[ConfigKey.IGNORE_HTTPS_ERRORS], + [ConfigKey.SCREENSHOTS]: monitor.screenshot || defaultFields[ConfigKey.SCREENSHOTS], + [ConfigKey.PLAYWRIGHT_OPTIONS]: Object.keys(monitor.playwrightOptions || {}).length + ? JSON.stringify(monitor.playwrightOptions) + : defaultFields[ConfigKey.PLAYWRIGHT_OPTIONS], + [ConfigKey.PARAMS]: Object.keys(monitor.params || {}).length + ? JSON.stringify(monitor.params) + : defaultFields[ConfigKey.PARAMS], + [ConfigKey.JOURNEY_FILTERS_MATCH]: + monitor.filter?.match || defaultFields[ConfigKey.JOURNEY_FILTERS_MATCH], + [ConfigKey.TIMEOUT]: monitor.timeout + ? getValueInSeconds(monitor.timeout) + : defaultFields[ConfigKey.TIMEOUT], + }; + return { + normalizedFields: { + ...defaultFields, + ...normalizedFields, + }, + unsupportedKeys: [], + }; +}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts new file mode 100644 index 0000000000000..31aebd0e8586e --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { omit } from 'lodash'; +import { formatKibanaNamespace } from '../../../../common/formatters'; +import { + BrowserFields, + ConfigKey, + CommonFields, + DataStream, + PrivateLocation, + Locations, + ProjectMonitor, + ScheduleUnit, + SourceType, +} from '../../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; +import { DEFAULT_COMMON_FIELDS } from '../../../../common/constants/monitor_defaults'; +import { NormalizedProjectProps } from '.'; + +export const getNormalizeCommonFields = ({ + locations = [], + privateLocations = [], + monitor, + projectId, + namespace, +}: NormalizedProjectProps): CommonFields => { + const defaultFields = DEFAULT_COMMON_FIELDS; + + const normalizedFields = { + [ConfigKey.JOURNEY_ID]: monitor.id || defaultFields[ConfigKey.JOURNEY_ID], + [ConfigKey.MONITOR_SOURCE_TYPE]: SourceType.PROJECT, + [ConfigKey.NAME]: monitor.name || '', + [ConfigKey.SCHEDULE]: { + number: `${monitor.schedule}`, + unit: ScheduleUnit.MINUTES, + }, + [ConfigKey.PROJECT_ID]: projectId, + [ConfigKey.LOCATIONS]: getMonitorLocations({ + monitor, + privateLocations, + publicLocations: locations, + }), + [ConfigKey.APM_SERVICE_NAME]: + monitor.apmServiceName || defaultFields[ConfigKey.APM_SERVICE_NAME], + [ConfigKey.TAGS]: getOptionalListField(monitor.tags) || defaultFields[ConfigKey.TAGS], + [ConfigKey.NAMESPACE]: formatKibanaNamespace(namespace) || defaultFields[ConfigKey.NAMESPACE], + [ConfigKey.ORIGINAL_SPACE]: namespace || defaultFields[ConfigKey.NAMESPACE], + [ConfigKey.CUSTOM_HEARTBEAT_ID]: getCustomHeartbeatId(monitor, projectId, namespace), + [ConfigKey.ENABLED]: monitor.enabled ?? defaultFields[ConfigKey.ENABLED], + }; + return { + ...defaultFields, + ...normalizedFields, + }; +}; + +export const getCustomHeartbeatId = ( + monitor: NormalizedProjectProps['monitor'], + projectId: string, + namespace: string +) => { + return `${monitor.id}-${projectId}-${namespace}`; +}; + +export const getMonitorLocations = ({ + privateLocations, + publicLocations, + monitor, +}: { + monitor: ProjectMonitor; + privateLocations: PrivateLocation[]; + publicLocations: Locations; +}) => { + const publicLocs = + monitor.locations?.map((id) => { + return publicLocations.find((location) => location.id === id); + }) || []; + const privateLocs = + monitor.privateLocations?.map((locationName) => { + return privateLocations.find( + (location) => + location.label.toLowerCase() === locationName.toLowerCase() || + location.id.toLowerCase() === locationName.toLowerCase() + ); + }) || []; + + return [...publicLocs, ...privateLocs].filter( + (location) => location !== undefined + ) as BrowserFields[ConfigKey.LOCATIONS]; +}; + +export const getValueInSeconds = (value: string) => { + const keyMap = { + h: 60 * 60, + m: 60, + s: 1, + }; + const key = value.slice(-1) as 'h' | 'm' | 's'; + const time = parseInt(value.slice(0, -1), 10); + const valueInSeconds = time * (keyMap[key] || 1); + return typeof valueInSeconds === 'number' ? `${valueInSeconds}` : null; +}; + +/** + * Accounts for array values that are optionally defined as a comma seperated list + * + * @param {Array | string} [value] + * @returns {array} Returns an array + */ +export const getOptionalListField = (value?: string[] | string): string[] => { + if (Array.isArray(value)) { + return value; + } + return value ? value.split(',') : []; +}; + +/** + * Accounts for heartbeat fields that are optionally an array or single string + * + * @param {Array | string} [value] + * @returns {string} Returns first item when the value is an array, or the value itself + */ +export const getOptionalArrayField = (value: string[] | string = '') => { + const array = getOptionalListField(value); + return array[0]; +}; + +/** + * Flattens arbitrary yaml into a synthetics monitor compatible configuration + * + * @param {Object} [monitor] + * @returns {Object} Returns an object containing synthetics-compatible configuration keys + */ +const flattenAndFormatObject = (obj: Record, prefix = '', keys: string[]) => + Object.keys(obj).reduce>((acc, k) => { + const pre = prefix.length ? prefix + '.' : ''; + const key = pre + k; + + /* If the key is an array of numbers, convert to an array of strings */ + if (Array.isArray(obj[k])) { + acc[key] = (obj[k] as unknown[]).map((value) => + typeof value === 'number' ? String(value) : value + ); + return acc; + } + + /* if the key is a supported key stop flattening early */ + if (keys.includes(key)) { + acc[key] = obj[k]; + return acc; + } + + if (typeof obj[k] === 'object') { + Object.assign(acc, flattenAndFormatObject(obj[k] as Record, pre + k, keys)); + } else { + acc[key] = obj[k]; + } + return acc; + }, {}); + +export const normalizeYamlConfig = (monitor: NormalizedProjectProps['monitor']) => { + const defaultFields = DEFAULT_FIELDS[monitor.type as DataStream]; + const supportedKeys = Object.keys(defaultFields); + const flattenedConfig = flattenAndFormatObject(monitor, '', supportedKeys); + const { + locations: _locations, + privateLocations: _privateLocations, + content: _content, + id: _id, + ...yamlConfig + } = flattenedConfig; + const unsupportedKeys = Object.keys(yamlConfig).filter((key) => !supportedKeys.includes(key)); + const supportedYamlConfig = omit(yamlConfig, unsupportedKeys); + + return { + yamlConfig: supportedYamlConfig, + unsupportedKeys, + }; +}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts new file mode 100644 index 0000000000000..6f637d818667a --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { getNormalizeCommonFields } from './common_fields'; +import { NormalizedProjectProps } from './browser_monitor'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; +import { + ConfigKey, + DataStream, + FormMonitorType, + HTTPFields, +} from '../../../../common/runtime_types/monitor_management'; +import { normalizeYamlConfig, getValueInSeconds, getOptionalArrayField } from './common_fields'; + +export const getNormalizeHTTPFields = ({ + locations = [], + privateLocations = [], + monitor, + projectId, + namespace, +}: NormalizedProjectProps): { normalizedFields: HTTPFields; unsupportedKeys: string[] } => { + const defaultFields = DEFAULT_FIELDS[DataStream.HTTP]; + const { yamlConfig, unsupportedKeys } = normalizeYamlConfig(monitor); + + const commonFields = getNormalizeCommonFields({ + locations, + privateLocations, + monitor, + projectId, + namespace, + }); + + const normalizedFields = { + ...yamlConfig, + ...commonFields, + [ConfigKey.MONITOR_TYPE]: DataStream.HTTP, + [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.HTTP, + [ConfigKey.URLS]: getOptionalArrayField(monitor.urls) || defaultFields[ConfigKey.URLS], + [ConfigKey.MAX_REDIRECTS]: + monitor[ConfigKey.MAX_REDIRECTS] || defaultFields[ConfigKey.MAX_REDIRECTS], + [ConfigKey.TIMEOUT]: monitor.timeout + ? getValueInSeconds(monitor.timeout) + : defaultFields[ConfigKey.TIMEOUT], + }; + return { + normalizedFields: { + ...defaultFields, + ...normalizedFields, + }, + unsupportedKeys, + }; +}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.ts new file mode 100644 index 0000000000000..282475f94d7cd --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getNormalizeCommonFields } from './common_fields'; +import { NormalizedProjectProps } from './browser_monitor'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; +import { + ConfigKey, + DataStream, + FormMonitorType, + ICMPFields, +} from '../../../../common/runtime_types/monitor_management'; +import { normalizeYamlConfig, getValueInSeconds, getOptionalArrayField } from './common_fields'; + +export const getNormalizeICMPFields = ({ + locations = [], + privateLocations = [], + monitor, + projectId, + namespace, +}: NormalizedProjectProps): { normalizedFields: ICMPFields; unsupportedKeys: string[] } => { + const defaultFields = DEFAULT_FIELDS[DataStream.ICMP]; + const { yamlConfig, unsupportedKeys } = normalizeYamlConfig(monitor); + + const commonFields = getNormalizeCommonFields({ + locations, + privateLocations, + monitor, + projectId, + namespace, + }); + + const normalizedFields = { + ...yamlConfig, + ...commonFields, + [ConfigKey.MONITOR_TYPE]: DataStream.ICMP, + [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.ICMP, + [ConfigKey.HOSTS]: + getOptionalArrayField(monitor[ConfigKey.HOSTS]) || defaultFields[ConfigKey.HOSTS], + [ConfigKey.TIMEOUT]: monitor.timeout + ? getValueInSeconds(monitor.timeout) + : defaultFields[ConfigKey.TIMEOUT], + [ConfigKey.WAIT]: monitor.wait + ? getValueInSeconds(monitor.wait) || defaultFields[ConfigKey.WAIT] + : defaultFields[ConfigKey.WAIT], + }; + return { + normalizedFields: { + ...defaultFields, + ...normalizedFields, + }, + unsupportedKeys, + }; +}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/index.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/index.ts new file mode 100644 index 0000000000000..82b2acfacbf5b --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/index.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + DataStream, + PrivateLocation, + Locations, + ProjectMonitor, +} from '../../../../common/runtime_types'; +import { getNormalizeBrowserFields } from './browser_monitor'; +import { getNormalizeICMPFields } from './icmp_monitor'; +import { getNormalizeTCPFields } from './tcp_monitor'; +import { getNormalizeHTTPFields } from './http_monitor'; + +export interface NormalizedProjectProps { + locations: Locations; + privateLocations: PrivateLocation[]; + monitor: ProjectMonitor; + projectId: string; + namespace: string; +} + +export const normalizeProjectMonitor = (props: NormalizedProjectProps) => { + const { monitor } = props; + const type = monitor.type || DataStream.BROWSER; + + switch (type) { + case DataStream.BROWSER: + return getNormalizeBrowserFields(props); + + case DataStream.HTTP: + return getNormalizeHTTPFields(props); + + case DataStream.TCP: + return getNormalizeTCPFields(props); + + case DataStream.ICMP: + return getNormalizeICMPFields(props); + default: + throw new Error(`Unsupported monitor type ${monitor.type}`); + } +}; + +export const normalizeProjectMonitors = ({ + locations = [], + privateLocations = [], + monitors = [], + projectId, + namespace, +}: { + locations: Locations; + privateLocations: PrivateLocation[]; + monitors: ProjectMonitor[]; + projectId: string; + namespace: string; +}) => { + return monitors.map((monitor) => { + return normalizeProjectMonitor({ monitor, locations, privateLocations, projectId, namespace }); + }); +}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.ts new file mode 100644 index 0000000000000..8a85b2959d804 --- /dev/null +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { NormalizedProjectProps } from './browser_monitor'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; +import { normalizeYamlConfig, getValueInSeconds } from './common_fields'; + +import { + ConfigKey, + DataStream, + FormMonitorType, + TCPFields, +} from '../../../../common/runtime_types/monitor_management'; +import { getNormalizeCommonFields, getOptionalArrayField } from './common_fields'; + +export const getNormalizeTCPFields = ({ + locations = [], + privateLocations = [], + monitor, + projectId, + namespace, +}: NormalizedProjectProps): { normalizedFields: TCPFields; unsupportedKeys: string[] } => { + const defaultFields = DEFAULT_FIELDS[DataStream.TCP]; + const { yamlConfig, unsupportedKeys } = normalizeYamlConfig(monitor); + + const commonFields = getNormalizeCommonFields({ + locations, + privateLocations, + monitor, + projectId, + namespace, + }); + + const normalizedFields = { + ...yamlConfig, + ...commonFields, + [ConfigKey.MONITOR_TYPE]: DataStream.TCP, + [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.TCP, + [ConfigKey.HOSTS]: + getOptionalArrayField(monitor[ConfigKey.HOSTS]) || defaultFields[ConfigKey.HOSTS], + [ConfigKey.TIMEOUT]: monitor.timeout + ? getValueInSeconds(monitor.timeout) + : defaultFields[ConfigKey.TIMEOUT], + }; + return { + normalizedFields: { + ...defaultFields, + ...normalizedFields, + }, + unsupportedKeys, + }; +}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts similarity index 97% rename from x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.test.ts rename to x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts index e7175bec58057..a5fb9b774cf2c 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts @@ -10,20 +10,21 @@ import { INSUFFICIENT_FLEET_PERMISSIONS, ProjectMonitorFormatter, } from './project_monitor_formatter'; -import { LocationStatus } from '../../common/runtime_types'; +import { LocationStatus } from '../../../common/runtime_types'; import { times } from 'lodash'; -import { SyntheticsService } from './synthetics_service'; -import { UptimeServerSetup } from '../legacy_uptime/lib/adapters'; +import { SyntheticsService } from '../synthetics_service'; +import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; -import { SyntheticsMonitorClient } from './synthetics_monitor/synthetics_monitor_client'; +import { SyntheticsMonitorClient } from '../synthetics_monitor/synthetics_monitor_client'; import { httpServerMock } from '@kbn/core-http-server-mocks'; import { Subject } from 'rxjs'; -import { formatSecrets } from './utils'; +import { formatSecrets } from '../utils'; -import * as telemetryHooks from '../routes/telemetry/monitor_upgrade_sender'; +import * as telemetryHooks from '../../routes/telemetry/monitor_upgrade_sender'; const testMonitors = [ { + type: 'browser', throttling: { download: 5, upload: 3, latency: 20 }, schedule: 3, locations: [], @@ -46,6 +47,7 @@ const testMonitors = [ filter: { match: 'check if title is present 10 0' }, }, { + type: 'browser', throttling: { download: 5, upload: 3, latency: 20 }, schedule: 3, locations: [], diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts similarity index 82% rename from x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts rename to x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts index b859f37ed87fc..744003d16ea3f 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.ts @@ -13,30 +13,34 @@ import { SavedObjectsFindResult, } from '@kbn/core/server'; import { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server'; -import { syncNewMonitorBulk } from '../routes/monitor_cruds/bulk_cruds/add_monitor_bulk'; -import { deleteMonitorBulk } from '../routes/monitor_cruds/bulk_cruds/delete_monitor_bulk'; -import { SyntheticsMonitorClient } from './synthetics_monitor/synthetics_monitor_client'; +import { syncNewMonitorBulk } from '../../routes/monitor_cruds/bulk_cruds/add_monitor_bulk'; +import { deleteMonitorBulk } from '../../routes/monitor_cruds/bulk_cruds/delete_monitor_bulk'; +import { SyntheticsMonitorClient } from '../synthetics_monitor/synthetics_monitor_client'; import { BrowserFields, ConfigKey, SyntheticsMonitorWithSecrets, EncryptedSyntheticsMonitor, ServiceLocationErrors, - ProjectBrowserMonitor, + ProjectMonitor, Locations, SyntheticsMonitor, MonitorFields, PrivateLocation, -} from '../../common/runtime_types'; +} from '../../../common/runtime_types'; import { syntheticsMonitorType, syntheticsMonitor, -} from '../legacy_uptime/lib/saved_objects/synthetics_monitor'; -import { normalizeProjectMonitor } from './normalizers/browser'; -import { formatSecrets, normalizeSecrets } from './utils/secrets'; -import { syncEditedMonitor } from '../routes/monitor_cruds/edit_monitor'; -import { validateProjectMonitor } from '../routes/monitor_cruds/monitor_validation'; -import type { UptimeServerSetup } from '../legacy_uptime/lib/adapters/framework'; +} from '../../legacy_uptime/lib/saved_objects/synthetics_monitor'; +import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters'; +import { formatSecrets, normalizeSecrets } from '../utils/secrets'; +import { syncEditedMonitor } from '../../routes/monitor_cruds/edit_monitor'; +import { + validateProjectMonitor, + validateMonitor, + ValidationResult, +} from '../../routes/monitor_cruds/monitor_validation'; +import { normalizeProjectMonitor } from './normalizers'; interface StaleMonitor { stale: boolean; @@ -44,7 +48,7 @@ interface StaleMonitor { savedObjectId: string; } type StaleMonitorMap = Record; -type FailedMonitors = Array<{ id?: string; reason: string; details: string; payload?: object }>; +type FailedError = Array<{ id?: string; reason: string; details: string; payload?: object }>; export const INSUFFICIENT_FLEET_PERMISSIONS = 'Insufficient permissions. In order to configure private locations, you must have Fleet and Integrations write permissions. To resolve, please generate a new API key with a user who has Fleet and Integrations write permissions.'; @@ -58,13 +62,13 @@ export class ProjectMonitorFormatter { private savedObjectsClient: SavedObjectsClientContract; private encryptedSavedObjectsClient: EncryptedSavedObjectsClient; private staleMonitorsMap: StaleMonitorMap = {}; - private monitors: ProjectBrowserMonitor[] = []; + private monitors: ProjectMonitor[] = []; public createdMonitors: string[] = []; public deletedMonitors: string[] = []; public updatedMonitors: string[] = []; public staleMonitors: string[] = []; - public failedMonitors: FailedMonitors = []; - public failedStaleMonitors: FailedMonitors = []; + public failedMonitors: FailedError = []; + public failedStaleMonitors: FailedError = []; private server: UptimeServerSetup; private projectFilter: string; private syntheticsMonitorClient: SyntheticsMonitorClient; @@ -94,7 +98,7 @@ export class ProjectMonitorFormatter { encryptedSavedObjectsClient: EncryptedSavedObjectsClient; projectId: string; spaceId: string; - monitors: ProjectBrowserMonitor[]; + monitors: ProjectMonitor[]; server: UptimeServerSetup; syntheticsMonitorClient: SyntheticsMonitorClient; request: KibanaRequest; @@ -138,9 +142,9 @@ export class ProjectMonitorFormatter { if (this.staleMonitorsMap[monitor.id]) { this.staleMonitorsMap[monitor.id].stale = false; } - normalizedUpdateMonitors.push(normM); + normalizedUpdateMonitors.push(normM as MonitorFields); } else { - normalizedNewMonitors.push(normM); + normalizedNewMonitors.push(normM as MonitorFields); } } } @@ -152,7 +156,7 @@ export class ProjectMonitorFormatter { await this.handleStaleMonitors(); }; - validatePermissions = async ({ monitor }: { monitor: ProjectBrowserMonitor }) => { + validatePermissions = async ({ monitor }: { monitor: ProjectMonitor }) => { if (this.writeIntegrationPoliciesPermissions || (monitor.privateLocations ?? []).length === 0) { return; } @@ -167,11 +171,11 @@ export class ProjectMonitorFormatter { } }; - validateProjectMonitor = async ({ monitor }: { monitor: ProjectBrowserMonitor }) => { + validateProjectMonitor = async ({ monitor }: { monitor: ProjectMonitor }) => { try { await this.validatePermissions({ monitor }); - const normalizedMonitor = normalizeProjectMonitor({ + const { normalizedFields: normalizedMonitor, unsupportedKeys } = normalizeProjectMonitor({ monitor, locations: this.locations, privateLocations: this.privateLocations, @@ -179,19 +183,40 @@ export class ProjectMonitorFormatter { namespace: this.spaceId, }); - const validationResult = validateProjectMonitor(monitor, this.projectId); - - if (!validationResult.valid) { - const { reason: message, details, payload } = validationResult; + if (unsupportedKeys.length) { this.failedMonitors.push({ id: monitor.id, - reason: message, - details, - payload, + reason: 'Unsupported Heartbeat option', + details: `The following Heartbeat options are not supported for ${ + monitor.type + } project monitors in ${this.server.kibanaVersion}: ${unsupportedKeys.join('|')}`, }); - if (this.staleMonitorsMap[monitor.id]) { - this.staleMonitorsMap[monitor.id].stale = false; - } + this.handleStreamingMessage({ + message: `${monitor.id}: failed to create or update monitor`, + }); + return null; + } + + /* Validates that the payload sent from the synthetics agent is valid */ + const { valid: isMonitorPayloadValid } = this.validateMonitor({ + validationResult: validateProjectMonitor({ + ...monitor, + type: normalizedMonitor[ConfigKey.MONITOR_TYPE], + }), + monitorId: monitor.id, + }); + + if (!isMonitorPayloadValid) { + return null; + } + + /* Validates that the normalized monitor is a valid monitor saved object type */ + const { valid: isNormalizedMonitorValid } = this.validateMonitor({ + validationResult: validateMonitor(normalizedMonitor as MonitorFields), + monitorId: monitor.id, + }); + + if (!isNormalizedMonitorValid) { return null; } @@ -310,7 +335,7 @@ export class ProjectMonitorFormatter { try { for (const monitor of monitors) { const previousMonitor = await this.getExistingMonitor(monitor[ConfigKey.JOURNEY_ID]!); - await this.updateMonitor(previousMonitor, monitor); + await this.updateMonitor(previousMonitor, monitor as MonitorFields); } if (monitors.length > 0) { @@ -335,7 +360,7 @@ export class ProjectMonitorFormatter { private updateMonitor = async ( previousMonitor: SavedObjectsFindResult, - normalizedMonitor: BrowserFields + normalizedMonitor: MonitorFields ): Promise<{ editedMonitor: SavedObjectsUpdateResponse; errors: ServiceLocationErrors; @@ -478,4 +503,26 @@ export class ProjectMonitorFormatter { this.subject?.next(message); } }; + + private validateMonitor = ({ + validationResult, + monitorId, + }: { + validationResult: ValidationResult; + monitorId: string; + }) => { + const { reason: message, details, payload: validationPayload, valid } = validationResult; + if (!valid) { + this.failedMonitors.push({ + id: monitorId, + reason: message, + details, + payload: validationPayload, + }); + if (this.staleMonitorsMap[monitorId]) { + this.staleMonitorsMap[monitorId].stale = false; + } + } + return validationResult; + }; } diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 266d8e3d20fe4..23f3a1dbd18c9 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -265,6 +265,23 @@ "type": "long" } } + }, + "count_connector_types_by_action_run_outcome_per_day": { + "properties": { + "DYNAMIC_KEY": { + "properties": { + "success": { + "type": "long" + }, + "failure": { + "type": "long" + }, + "unknown": { + "type": "long" + } + } + } + } } } }, @@ -1693,6 +1710,19 @@ } } }, + "count_rules_by_execution_status_per_day": { + "properties": { + "success": { + "type": "long" + }, + "failure": { + "type": "long" + }, + "unknown": { + "type": "long" + } + } + }, "avg_execution_time_per_day": { "type": "long" }, @@ -4917,6 +4947,62 @@ } } }, + "cloud_security_posture": { + "properties": { + "indices": { + "properties": { + "findings": { + "properties": { + "doc_count": { + "type": "long" + }, + "deleted": { + "type": "long" + }, + "size_in_bytes": { + "type": "long" + }, + "last_doc_timestamp": { + "type": "date" + } + } + }, + "latest_findings": { + "properties": { + "doc_count": { + "type": "long" + }, + "deleted": { + "type": "long" + }, + "size_in_bytes": { + "type": "long" + }, + "last_doc_timestamp": { + "type": "date" + } + } + }, + "score": { + "properties": { + "doc_count": { + "type": "long" + }, + "deleted": { + "type": "long" + }, + "size_in_bytes": { + "type": "long" + }, + "last_doc_timestamp": { + "type": "date" + } + } + } + } + } + } + }, "discoverEnhanced": { "properties": { "exploreDataInChartActionEnabled": { diff --git a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts index ccd91253012b3..f9f1252f4765e 100644 --- a/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts +++ b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts @@ -25,6 +25,9 @@ import { ENDING_BREADCRUMB, FIELD_BROWSER, FIELD_BROWSER_MODAL, + FIELD_SELECTOR_TOGGLE_BUTTON, + FIELD_SELECTOR_INPUT, + FIELD_SELECTOR_LIST, } from '../screens/indicators'; import { login } from '../tasks/login'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; @@ -143,16 +146,13 @@ describe('Indicators', () => { it('should have the default selected field, then update when user selects', () => { const threatFeedName = 'threat.feed.name'; - cy.get(`${FIELD_SELECTOR}`).should('have.value', threatFeedName); + cy.get(`${FIELD_SELECTOR_INPUT}`).eq(0).should('have.text', threatFeedName); const threatIndicatorIp: string = 'threat.indicator.ip'; - cy.get(`${FIELD_SELECTOR}`) - .should('exist') - .select(threatIndicatorIp) - .should('have.value', threatIndicatorIp); + cy.get(`${FIELD_SELECTOR_TOGGLE_BUTTON}`).should('exist').click(); - cy.get(`${FIELD_SELECTOR}`).should('have.value', threatIndicatorIp); + cy.get(`${FIELD_SELECTOR_LIST}`).should('exist').contains(threatIndicatorIp); }); }); diff --git a/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts b/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts index 4ceaa0c020e99..b5582da6ce8ef 100644 --- a/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts +++ b/x-pack/plugins/threat_intelligence/cypress/screens/indicators.ts @@ -41,6 +41,12 @@ export const INDICATOR_TYPE_CELL = '[data-gridcell-column-id="threat.indicator.t export const FIELD_SELECTOR = '[data-test-subj="tiIndicatorFieldSelectorDropdown"]'; +export const FIELD_SELECTOR_INPUT = '[data-test-subj="comboBoxInput"]'; + +export const FIELD_SELECTOR_TOGGLE_BUTTON = '[data-test-subj="comboBoxToggleListButton"]'; + +export const FIELD_SELECTOR_LIST = '[data-test-subj="comboBoxOptionsList"]'; + export const FIELD_BROWSER = `[data-test-subj="show-field-browser"]`; export const FIELD_BROWSER_MODAL = `[data-test-subj="fields-browser-container"]`; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_barchart_wrapper/__snapshots__/indicators_barchart_wrapper.test.tsx.snap b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_barchart_wrapper/__snapshots__/indicators_barchart_wrapper.test.tsx.snap index de4d6c198961f..bc2b71303138b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_barchart_wrapper/__snapshots__/indicators_barchart_wrapper.test.tsx.snap +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_barchart_wrapper/__snapshots__/indicators_barchart_wrapper.test.tsx.snap @@ -21,43 +21,67 @@ Object { class="euiFlexItem euiFlexItem--flexGrowZero" >
-
- + Stack by +
- + class="euiComboBoxPill euiComboBoxPill--plainText" + > + threat.feed.name + +
+ +
+
+
+
+ +
@@ -102,43 +126,67 @@ Object { class="euiFlexItem euiFlexItem--flexGrowZero" >
-
- + Stack by +
- + class="euiComboBoxPill euiComboBoxPill--plainText" + > + threat.feed.name + +
+ +
+
+
+
+ +
diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_browser/indicators_field_browser.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_browser/indicators_field_browser.tsx index 2adcc4ee5b9ee..22cada18b84d8 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_browser/indicators_field_browser.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_browser/indicators_field_browser.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { BrowserField } from '@kbn/triggers-actions-ui-plugin/public/application/sections/field_browser/types'; +import { BrowserField } from '@kbn/rule-registry-plugin/common'; import { VFC } from 'react'; import { useKibana } from '../../../../hooks/use_kibana'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/__snapshots__/indicators_field_selector.test.tsx.snap b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/__snapshots__/indicators_field_selector.test.tsx.snap index 735a1c34718c0..9346a739b9dae 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/__snapshots__/indicators_field_selector.test.tsx.snap +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/__snapshots__/indicators_field_selector.test.tsx.snap @@ -6,43 +6,67 @@ Object { "baseElement":
-
- + Stack by +
- + class="euiComboBoxPill euiComboBoxPill--plainText" + > + threat.feed.name + +
+ +
+
+
+
+ +
@@ -50,43 +74,67 @@ Object { , "container":
-
- + Stack by +
- + class="euiComboBoxPill euiComboBoxPill--plainText" + > + threat.feed.name + +
+ +
+
+
+
+ +
@@ -151,32 +199,67 @@ Object { "baseElement":
-
- +
+
+
+
+ +
@@ -184,32 +267,67 @@ Object { , "container":
-
- +
+
+
+
+ +
diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/indicators_field_selector.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/indicators_field_selector.test.tsx index e3bd4129d4fc5..0d62bbcef6219 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/indicators_field_selector.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_field_selector/indicators_field_selector.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; -import { DROPDOWN_TEST_ID, IndicatorsFieldSelector } from './indicators_field_selector'; +import { IndicatorsFieldSelector } from './indicators_field_selector'; const mockIndexPattern: DataView = { fields: [ @@ -51,11 +51,5 @@ describe('', () => { ); expect(component).toMatchSnapshot(); - - const dropdownOptions: string = component.getByTestId(DROPDOWN_TEST_ID).innerHTML; - const optionsCount: number = (dropdownOptions.match(/