diff --git a/.ci/Jenkinsfile_baseline_capture b/.ci/Jenkinsfile_baseline_capture
index 7c7cc8d98c306..3f90a6bc05af0 100644
--- a/.ci/Jenkinsfile_baseline_capture
+++ b/.ci/Jenkinsfile_baseline_capture
@@ -8,12 +8,12 @@ kibanaPipeline(timeoutMinutes: 120) {
catchError {
parallel([
'oss-visualRegression': {
- workers.ci(name: 'oss-visualRegression', size: 's', ramDisk: false) {
+ workers.ci(name: 'oss-visualRegression', size: 's-highmem', ramDisk: true) {
kibanaPipeline.functionalTestProcess('oss-visualRegression', './test/scripts/jenkins_visual_regression.sh')(1)
}
},
'xpack-visualRegression': {
- workers.ci(name: 'xpack-visualRegression', size: 's', ramDisk: false) {
+ workers.ci(name: 'xpack-visualRegression', size: 's-highmem', ramDisk: true) {
kibanaPipeline.functionalTestProcess('xpack-visualRegression', './test/scripts/jenkins_xpack_visual_regression.sh')(1)
}
},
diff --git a/NOTICE.txt b/NOTICE.txt
index 56280e6e3883e..e1552852d0349 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -26,9 +26,6 @@ This module was heavily inspired by the externals plugin that ships with webpack
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
----
-This product has relied on ASTExplorer that is licensed under MIT.
-
---
This product includes code that is based on Ace editor, which was available
under a "BSD" license.
diff --git a/docs/dev-tools/grokdebugger/index.asciidoc b/docs/dev-tools/grokdebugger/index.asciidoc
index 5162e806edd07..994836de7a1a2 100644
--- a/docs/dev-tools/grokdebugger/index.asciidoc
+++ b/docs/dev-tools/grokdebugger/index.asciidoc
@@ -32,7 +32,7 @@ in ingest node and Logstash.
This example walks you through using the *Grok Debugger*. This tool
is automatically enabled in {kib}.
-NOTE: If you're using {security}, you must have the `manage_pipeline`
+NOTE: If you're using {stack-security-features}, you must have the `manage_pipeline`
permission to use the Grok Debugger.
. Open the menu, go to *Dev Tools*, then click *Grok Debugger*.
diff --git a/docs/developer/architecture/code-exploration.asciidoc b/docs/developer/architecture/code-exploration.asciidoc
index 23ba1c54d27d3..2f67ae002c916 100644
--- a/docs/developer/architecture/code-exploration.asciidoc
+++ b/docs/developer/architecture/code-exploration.asciidoc
@@ -11,7 +11,7 @@ NOTE:
////
[[code-exploration]]
-=== Exploring Kibana code
+== Exploring Kibana code
The goals of our folder heirarchy are:
@@ -28,10 +28,10 @@ To that aim, we strive to:
[discrete]
[[kibana-services-applications]]
-==== Services and Applications
+=== Services and Applications
[discrete]
-===== src/plugins
+==== src/plugins
- {kib-repo}blob/{branch}/src/plugins/advanced_settings[advancedSettings]
@@ -283,7 +283,7 @@ WARNING: Missing README.
[discrete]
-===== x-pack/plugins
+==== x-pack/plugins
- {kib-repo}blob/{branch}/x-pack/plugins/actions/README.md[actions]
@@ -365,7 +365,10 @@ WARNING: Missing README.
WARNING: Missing README.
-- {kib-repo}blob/{branch}/x-pack/plugins/embeddable_enhanced/README.md[embeddableEnhanced]
+- {kib-repo}blob/{branch}/x-pack/plugins/embeddable_enhanced[embeddableEnhanced]
+
+WARNING: Missing README.
+
- {kib-repo}blob/{branch}/x-pack/plugins/encrypted_saved_objects/README.md[encryptedSavedObjects]
diff --git a/docs/drilldowns/explore-underlying-data.asciidoc b/docs/drilldowns/explore-underlying-data.asciidoc
new file mode 100644
index 0000000000000..e0f940f73e96e
--- /dev/null
+++ b/docs/drilldowns/explore-underlying-data.asciidoc
@@ -0,0 +1,41 @@
+[[explore-underlying-data]]
+== Explore the underlying data for a visualization
+
+++++
+Explore the underlying data
+++++
+
+Dashboard panels have an *Explore underlying data* action that navigates you to *Discover*,
+where you can narrow your documents to the ones you'll most likely use in a visualization.
+This action is available for visualizations backed by a single index pattern.
+
+You can access *Explore underlying data* in two ways: from the panel context
+menu or from the menu that appears when you interact with the chart.
+
+[float]
+[[explore-data-from-panel-context-menu]]
+=== Explore data from panel context menu
+
+The *Explore underlying data* action in the panel menu navigates you to Discover,
+carrying over the index pattern, filters, query, and time range for the visualization.
+
+[role="screenshot"]
+image::images/explore_data_context_menu.png[Explore underlying data from panel context menu]
+
+[float]
+[[explore-data-from-chart]]
+=== Explore data from chart action
+
+Initiating *Explore underlying data* from the chart also navigates to Discover,
+carrying over the current context for the visualization. In addition, this action
+applies the filters and time range created by the events that triggered the action.
+
+[role="screenshot"]
+image::images/explore_data_in_chart.png[Explore underlying data from chart]
+
+You can disable this action by adding the following line to your `kibana.yml` config.
+
+["source","yml"]
+-----------
+xpack.discoverEnhanced.actions.exploreDataInChart.enabled: false
+-----------
diff --git a/docs/drilldowns/images/explore_data_context_menu.png b/docs/drilldowns/images/explore_data_context_menu.png
new file mode 100644
index 0000000000000..5742991030c89
Binary files /dev/null and b/docs/drilldowns/images/explore_data_context_menu.png differ
diff --git a/docs/drilldowns/images/explore_data_in_chart.png b/docs/drilldowns/images/explore_data_in_chart.png
new file mode 100644
index 0000000000000..05d4f5fac9b2f
Binary files /dev/null and b/docs/drilldowns/images/explore_data_in_chart.png differ
diff --git a/docs/maps/heatmap-layer.asciidoc b/docs/maps/heatmap-layer.asciidoc
index 7149bc5623169..9dc2781db44a3 100644
--- a/docs/maps/heatmap-layer.asciidoc
+++ b/docs/maps/heatmap-layer.asciidoc
@@ -7,8 +7,8 @@ Heat map layers cluster point data to show locations with higher densities.
[role="screenshot"]
image::maps/images/heatmap_layer.png[]
-To add a heat map layer to your map, click *Add layer*, then select the *Heat map* layer.
-The index must contain at least one field mapped as {ref}/geo-point.html[geo_point].
+To add a heat map layer to your map, click *Add layer*, then select *Heat map*.
+The index must contain at least one field mapped as {ref}/geo-point.html[geo_point] or {ref}/geo-shape.html[geo_shape].
NOTE: Only count, sum, unique count metric aggregations are available with the grid aggregation source and heat map layers.
Average, min, and max are turned off because the heat map will blend nearby values.
diff --git a/docs/maps/maps-aggregations.asciidoc b/docs/maps/maps-aggregations.asciidoc
index 872ed1cdedb7e..6b2dc8077bc30 100644
--- a/docs/maps/maps-aggregations.asciidoc
+++ b/docs/maps/maps-aggregations.asciidoc
@@ -47,7 +47,7 @@ Grid aggregation layers use {ref}/search-aggregations-bucket-geotilegrid-aggrega
Symbolize grid aggregation metrics as:
*Clusters*:: Creates a <> with a cluster symbol for each gridded cell.
-The cluster location is the weighted centroid for all geo-points in the gridded cell.
+The cluster location is the weighted centroid for all documents in the gridded cell.
*Grid rectangles*:: Creates a <> with a bounding box polygon for each gridded cell.
@@ -60,7 +60,7 @@ To enable a grid aggregation layer:
To enable a blended layer that dynamically shows clusters or documents:
. Click *Add layer*, then select the *Documents* layer.
-. Configure *Index pattern* and the *Geospatial field*. To enable clustering, the *Geospatial field* must be set to a field mapped as {ref}/geo-point.html[geo_point].
+. Configure *Index pattern* and the *Geospatial field*.
. In *Scaling*, select *Show clusters when results exceed 10000*.
diff --git a/docs/maps/maps-getting-started.asciidoc b/docs/maps/maps-getting-started.asciidoc
index 09a4dc61cae28..e0d43a571a331 100644
--- a/docs/maps/maps-getting-started.asciidoc
+++ b/docs/maps/maps-getting-started.asciidoc
@@ -68,40 +68,17 @@ The first layer you'll add is a choropleth layer to shade world countries
by web log traffic. Darker shades symbolize countries with more web log traffic,
and lighter shades symbolize countries with less traffic.
-==== Add a vector layer to display world country boundaries
-
. Click *Add layer*.
-. Select the *EMS Boundaries* layer.
+. Select *Choropleth*.
. From the *Layer* dropdown menu, select *World Countries*.
+. Under *Statistics source*, set *Index pattern* to *kibana_sample_data_logs*.
+. Set *Join field* to *geo.src*.
. Click the *Add layer* button.
. Set *Name* to `Total Requests by Country`.
. Set *Opacity* to 50%.
. Click *Add* under *Tooltip fields*.
. In the popover, select *ISO 3166-1 alpha-2 code* and *name* and click *Add*.
-
-===== Join the vector layer with the sample web log index
-
-You now have a vector layer containing the world countries.
-To symbolize countries by web traffic, you'll need to augment the world country features with the count of Elasticsearch weblog documents originating from each country.
-To do this, you'll create a <> to link the vector source *World Countries* to
-the {es} index `kibana_sample_data_logs` on the shared key iso2 = geo.src.
-
-. Click plus image:maps/images/gs_plus_icon.png[] next to the *Term Joins* label.
-. Click *Join --select--*
-. Set *Left field* to *ISO 3166-1 alpha-2 code*.
-. Set *Right source* to *kibana_sample_data_logs*.
-. Set *Right field* to *geo.src*.
-. Click *and use metric count*.
-. Set *Custom label* to *web logs count*.
-
-===== Set the layer style
-
-All of the world countries are still a single color because the layer is using <>.
-To shade the world countries based on which country is sending the most requests, you'll need to use <>.
-
-. Under *Fill color*, change the selected value from *Solid* to *By value*.
-. In the field select input, select *web logs count*.
-. Select the grey color ramp.
+. Under *Fill color*, select the grey color ramp.
. Under *Border color*, change the selected color to *white*.
. Click *Save & close*.
+
@@ -127,7 +104,7 @@ This layer displays web log documents as points.
The layer is only visible when users zoom in the map past zoom level 9.
. Click *Add layer*.
-. Click the *Documents* layer.
+. Select *Documents*.
. Set *Index pattern* to *kibana_sample_data_logs*.
. Click the *Add layer* button.
. Set *Name* to `Actual Requests`.
@@ -161,7 +138,7 @@ image::maps/images/grid_metrics_both.png[]
===== Add the layer
. Click *Add layer*.
-. Click the *Clusters and grids* layer.
+. Select *Clusters and grids*.
. Set *Index pattern* to *kibana_sample_data_logs*.
. Click the *Add layer* button.
. Set *Name* to `Total Requests and Bytes`.
diff --git a/docs/maps/tile-layer.asciidoc b/docs/maps/tile-layer.asciidoc
index 6da8dbad0a66d..2a60504c3c790 100644
--- a/docs/maps/tile-layer.asciidoc
+++ b/docs/maps/tile-layer.asciidoc
@@ -7,7 +7,7 @@ Tile layers display image tiles served from a tile server.
[role="screenshot"]
image::maps/images/tile_layer.png[]
-To add a tile layer to your map, click *Add layer*, then select one of the following layers:
+To add a tile layer to your map, click *Add layer*, then select one of the following:
*Configured Tile Map Service*:: Tile map service configured in kibana.yml.
See map.tilemap.url in <> for details.
@@ -16,4 +16,6 @@ See map.tilemap.url in <> for details.
*Tile Map Service*:: Tile map service configured in interface.
+*Vector tiles*:: Data service implementing the Mapbox vector tile specification.
+
*Web Map Service*:: Maps from OGC Standard WMS.
diff --git a/docs/maps/vector-layer.asciidoc b/docs/maps/vector-layer.asciidoc
index d6a5931659a40..494bd915b7f56 100644
--- a/docs/maps/vector-layer.asciidoc
+++ b/docs/maps/vector-layer.asciidoc
@@ -7,15 +7,14 @@ Vector layers display points, lines, and polygons.
[role="screenshot"]
image::maps/images/vector_layer.png[]
-To add a vector layer to your map, click *Add layer*, then select one of the following layers:
+To add a vector layer to your map, click *Add layer*, then select one of the following:
-*Clusters and grids*:: Geospatial data grouped in grids with metrics for each gridded cell.
-The index must contain at least one field mapped as {ref}/geo-point.html[geo_point].
+*Choropleth*:: Shaded areas to compare statistics across boundaries.
-*Configured GeoJSON*:: Vector data from hosted GeoJSON configured in kibana.yml.
-See map.regionmap.* in <> for details.
+*Clusters and grids*:: Geospatial data grouped in grids with metrics for each gridded cell.
+The index must contain at least one field mapped as {ref}/geo-point.html[geo_point] or {ref}/geo-shape.html[geo_shape].
-*Documents*:: Vector data from a Kibana index pattern.
+*Documents*:: Points, lines, and polyons from Elasticsearch.
The index must contain at least one field mapped as {ref}/geo-point.html[geo_point] or {ref}/geo-shape.html[geo_shape].
NOTE: Document results are limited to the `index.max_result_window` index setting, which defaults to 10000.
diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc
index 48b5b5eb5d0c0..5b8fa0725d96b 100644
--- a/docs/settings/monitoring-settings.asciidoc
+++ b/docs/settings/monitoring-settings.asciidoc
@@ -7,7 +7,7 @@
By default, the Monitoring application is enabled, but data collection
is disabled. When you first start {kib} monitoring, you are prompted to
-enable data collection. If you are using {security}, you must be
+enable data collection. If you are using {stack-security-features}, you must be
signed in as a user with the `cluster:manage` privilege to enable
data collection. The built-in `superuser` role has this privilege and the
built-in `elastic` user has this role.
diff --git a/docs/setup/install.asciidoc b/docs/setup/install.asciidoc
index 73036da8f1390..cb47210cb3f08 100644
--- a/docs/setup/install.asciidoc
+++ b/docs/setup/install.asciidoc
@@ -53,8 +53,8 @@ Formulae are available from the Elastic Homebrew tap for installing {kib} on mac
<>
IMPORTANT: If your Elasticsearch installation is protected by
-{ref}/elasticsearch-security.html[{security}] see
-{kibana-ref}/using-kibana-with-security.html[Configuring security in Kibana] for
+{ref}/elasticsearch-security.html[{stack-security-features}] see
+{kibana-ref}/using-kibana-with-security.html[Configuring security in {kib}] for
additional setup instructions.
include::install/targz.asciidoc[]
diff --git a/docs/user/dashboard.asciidoc b/docs/user/dashboard.asciidoc
index a812d4e3bdd2d..b812af7e981bf 100644
--- a/docs/user/dashboard.asciidoc
+++ b/docs/user/dashboard.asciidoc
@@ -160,6 +160,7 @@ When you're finished adding and arranging the panels, save the dashboard.
. Enter the dashboard *Title* and optional *Description*, then *Save* the dashboard.
include::{kib-repo-dir}/drilldowns/drilldowns.asciidoc[]
+include::{kib-repo-dir}/drilldowns/explore-underlying-data.asciidoc[]
[[sharing-dashboards]]
== Share the dashboard
diff --git a/docs/user/monitoring/monitoring-kibana.asciidoc b/docs/user/monitoring/monitoring-kibana.asciidoc
index b9ec3982eb3c5..bb8b3e5d42851 100644
--- a/docs/user/monitoring/monitoring-kibana.asciidoc
+++ b/docs/user/monitoring/monitoring-kibana.asciidoc
@@ -20,9 +20,10 @@ node in the production cluster. By default, it is is disabled (`false`).
+
--
NOTE: You can specify this setting in either the `elasticsearch.yml` on each
-node or across the cluster as a dynamic cluster setting. If {es}
-{security-features} are enabled, you must have `monitor` cluster privileges to
-view the cluster settings and `manage` cluster privileges to change them.
+node or across the cluster as a dynamic cluster setting. If
+{stack-security-features} are enabled, you must have `monitor` cluster
+privileges to view the cluster settings and `manage` cluster privileges to
+change them.
--
@@ -33,7 +34,7 @@ view the cluster settings and `manage` cluster privileges to change them.
--
By default, if you are running {kib} locally, go to `http://localhost:5601/`.
-If {es} {security-features} are enabled, log in.
+If {security-features} are enabled, log in.
--
... Open the menu, then go to *Stack Monitoring*. If data collection is
@@ -80,13 +81,13 @@ monitoring cluster prevents production cluster outages from impacting your
ability to access your monitoring data. It also prevents monitoring activities
from impacting the performance of your production cluster.
-If {security} is enabled on the production cluster, use an HTTPS URL such
-as `https://:9200` in this setting.
+If {security-features} are enabled on the production cluster, use an HTTPS
+URL such as `https://:9200` in this setting.
===============================
--
-. If the Elastic {security-features} are enabled on the production cluster:
+. If {security-features} are enabled on the production cluster:
.. Verify that there is a
valid user ID and password in the `elasticsearch.username` and
diff --git a/docs/user/reporting/chromium-sandbox.asciidoc b/docs/user/reporting/chromium-sandbox.asciidoc
index bfef5b8b86c6b..dcb421261c067 100644
--- a/docs/user/reporting/chromium-sandbox.asciidoc
+++ b/docs/user/reporting/chromium-sandbox.asciidoc
@@ -2,14 +2,16 @@
[[reporting-chromium-sandbox]]
=== Chromium sandbox
-When {reporting} uses the Chromium browser for generating PDF reports, it's recommended to use the sandbox for
-an additional layer of security. The Chromium sandbox uses operating system provided mechanisms to ensure that
-code execution cannot make persistent changes to the computer or access confidential information. The specific
-sandboxing techniques differ for each operating system.
+When {report-features} uses the Chromium browser for generating PDF reports,
+it's recommended to use the sandbox for an additional layer of security. The
+Chromium sandbox uses operating system provided mechanisms to ensure that
+code execution cannot make persistent changes to the computer or access
+confidential information. The specific sandboxing techniques differ for each
+operating system.
==== Linux sandbox
The Linux sandbox depends on user namespaces, which were introduced with the 3.8 Linux kernel. However, many
-distributions don't have user namespaces enabled by default, or they require the CAP_SYS_ADMIN capability. {reporting}
+distributions don't have user namespaces enabled by default, or they require the CAP_SYS_ADMIN capability. The {report-features}
will automatically disable the sandbox when it is running on Debian and CentOS as additional steps are required to enable
unprivileged usernamespaces. In these situations, you'll see the following message in your {kib} startup logs:
`Chromium sandbox provides an additional layer of protection, but is not supported for your OS.
diff --git a/docs/user/reporting/configuring-reporting.asciidoc b/docs/user/reporting/configuring-reporting.asciidoc
index 7489e2cf51f61..ca2d79bb2dec0 100644
--- a/docs/user/reporting/configuring-reporting.asciidoc
+++ b/docs/user/reporting/configuring-reporting.asciidoc
@@ -2,8 +2,8 @@
[[configuring-reporting]]
== Reporting configuration
-You can configure settings in `kibana.yml` to control how {reporting}
-communicates with the {kib} server, manages background jobs, and captures
+You can configure settings in `kibana.yml` to control how the {report-features}
+communicate with the {kib} server, manages background jobs, and captures
screenshots. See <> for the complete
list of settings.
@@ -11,9 +11,9 @@ list of settings.
[[encryption-keys]]
=== Encryption keys for multiple {kib} instances
-By default, a new encryption key is generated for {reporting} each time
-you start {kib}. This means if a static encryption key is not persisted in the
-{kib} configuration, any pending reports will fail when you restart {kib}.
+By default, a new encryption key is generated for the {report-features} each
+time you start {kib}. This means if a static encryption key is not persisted in
+the {kib} configuration, any pending reports will fail when you restart {kib}.
If you are load balancing across multiple {kib} instances, they need to have
the same reporting encryption key. Otherwise, report generation will fail if a
diff --git a/docs/user/reporting/development/index.asciidoc b/docs/user/reporting/development/index.asciidoc
index a64e540da0c70..4e86c803bd82d 100644
--- a/docs/user/reporting/development/index.asciidoc
+++ b/docs/user/reporting/development/index.asciidoc
@@ -1,9 +1,11 @@
[role="xpack"]
[[reporting-integration]]
== Reporting integration
-Integrating a {kib} application with {reporting} requires a minimum amount of code, and the goal is to not have to
-modify the Reporting code as we add additional applications. Instead, applications abide by a contract that Reporting
-uses to determine the information that is required to export CSVs and PDFs.
+Integrating a {kib} application with the {report-features} requires a minimum
+amount of code, and the goal is to not have to modify the reporting code as we
+add additional applications. Instead, applications abide by a contract that
+{report-features} use to determine the information that is required to export
+CSVs and PDFs.
[IMPORTANT]
==============================================
@@ -18,7 +20,7 @@ X-Pack uses the `share` plugin of the Kibana platform to register actions in the
[float]
=== Generate job URL
-To generate a new {reporting} job, different export types require different `jobParams` that are Rison encoded into a URL
+To generate a new reporting job, different export types require different `jobParams` that are Rison encoded into a URL
that abide by the following convention: `/api/reporting/generate?jobParams=${rison.encode(jobParams)}`. If you use the
aforementioned <> then this detail will be abstracted away, but if you
provide a custom UI for generating the report, you will have to generate the URL and create a POST request to the URL.
diff --git a/docs/user/reporting/gs-index.asciidoc b/docs/user/reporting/gs-index.asciidoc
index 87918ee76340e..46c1fd38b7d69 100644
--- a/docs/user/reporting/gs-index.asciidoc
+++ b/docs/user/reporting/gs-index.asciidoc
@@ -21,7 +21,7 @@ You can also <>.
IMPORTANT: Reports are stored in the `.reporting-*` indices. Any user with
access to these indices has access to every report generated by all users.
-To use {reporting} in a production environment,
+To use {report-features} in a production environment,
<>.
--
diff --git a/docs/user/reporting/index.asciidoc b/docs/user/reporting/index.asciidoc
index 6acdbbe3f0a99..e4e4b461ac2bd 100644
--- a/docs/user/reporting/index.asciidoc
+++ b/docs/user/reporting/index.asciidoc
@@ -19,7 +19,7 @@ image::user/reporting/images/share-button.png["Share"]
[float]
== Setup
-{reporting} is automatically enabled in {kib}. It runs a custom build of the Chromium web browser, which
+The {report-features} are automatically enabled in {kib}. It runs a custom build of the Chromium web browser, which
runs on the server in headless mode to load {kib} and capture the rendered {kib} charts as images.
Chromium is an open-source project not related to Elastic, but the Chromium binary for {kib} has been custom-built by Elastic to ensure it
diff --git a/docs/user/reporting/script-example.asciidoc b/docs/user/reporting/script-example.asciidoc
index 88f48ad1d3182..94301fc6fb448 100644
--- a/docs/user/reporting/script-example.asciidoc
+++ b/docs/user/reporting/script-example.asciidoc
@@ -19,7 +19,8 @@ curl \
// CONSOLE
<1> `POST` method is required.
-<2> Provide user credentials for a user with permission to access Kibana and X-Pack reporting.
+<2> Provide user credentials for a user with permission to access Kibana and
+{report-features}.
<3> The `kbn-version` header is required for all `POST` requests to Kibana.
**The value must match the dotted-numeral version of the Kibana instance.**
<4> The POST URL. You can copy and paste the URL for any report from the Kibana UI.
diff --git a/docs/user/reporting/watch-example.asciidoc b/docs/user/reporting/watch-example.asciidoc
index 627e31017230c..253722fefecc0 100644
--- a/docs/user/reporting/watch-example.asciidoc
+++ b/docs/user/reporting/watch-example.asciidoc
@@ -52,7 +52,7 @@ report from the Kibana UI.
<3> Optional, default is 40
<4> Optional, default is 15s
<5> Provide user credentials for a user with permission to access Kibana and
-{reporting}.
+the {report-features}.
//For more information, see <>.
//<>.
diff --git a/docs/user/security/reporting.asciidoc b/docs/user/security/reporting.asciidoc
index 30340e1db989a..4e02759ce99cb 100644
--- a/docs/user/security/reporting.asciidoc
+++ b/docs/user/security/reporting.asciidoc
@@ -5,8 +5,8 @@
Reporting operates by creating and updating documents in {es} in response to
user actions in {kib}.
-To use {reporting} with {security} enabled, you need to
-<>.
+To use {report-features} with {security-features} enabled, you need to
+<>.
If you are automatically generating reports with
{ref}/xpack-alerting.html[{watcher}], you also need to configure {watcher}
to trust the {kib} server's certificate.
@@ -118,10 +118,10 @@ reporting_user:
=== Secure the reporting endpoints
In a production environment, you should restrict access to
-the {reporting} endpoints to authorized users. This requires that you:
+the reporting endpoints to authorized users. This requires that you:
-. Enable {security} on your {es} cluster. For more information,
-see {ref}/security-getting-started.html[Getting Started with Security].
+. Enable {stack-security-features} on your {es} cluster. For more information,
+see {ref}/security-getting-started.html[Getting started with security].
. Configure TLS/SSL encryption for the {kib} server. For more information, see
<>.
. Specify the {kib} server's CA certificate chain in `elasticsearch.yml`:
@@ -150,13 +150,13 @@ For more information, see {ref}/notification-settings.html#ssl-notification-sett
--
. Add one or more users who have the permissions
-necessary to use {kib} and {reporting}. For more information, see
+necessary to use {kib} and {report-features}. For more information, see
<>.
-Once you've enabled SSL for {kib}, all requests to the {reporting} endpoints
+Once you've enabled SSL for {kib}, all requests to the reporting endpoints
must include valid credentials. For example, see the following page which
includes a watch that submits requests as the built-in `elastic` user:
<>.
For more information about configuring watches, see
-{ref}/how-watcher-works.html[How Watcher works].
+{ref}/how-watcher-works.html[How {watcher} works].
diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc
index b30acd0ed2e53..0177ac94bd402 100644
--- a/docs/user/security/securing-kibana.asciidoc
+++ b/docs/user/security/securing-kibana.asciidoc
@@ -5,21 +5,21 @@
Configure security
++++
-{kib} users have to log in when {security} is enabled on your cluster. You
-configure {security} roles for your {kib} users to control what data those users
-can access.
+{kib} users have to log in when {stack-security-features} are enabled on your
+cluster. You configure roles for your {kib} users to control what data those
+users can access.
Most requests made through {kib} to {es} are authenticated by using the
credentials of the logged-in user. There are, however, a few internal requests
that the {kib} server needs to make to the {es} cluster. For this reason, you
must configure credentials for the {kib} server to use for those requests.
-With {security} enabled, if you load a {kib} dashboard that accesses data in an
-index that you are not authorized to view, you get an error that indicates the
-index does not exist. {security} do not currently provide a way to control which
-users can load which dashboards.
+With {security-features} enabled, if you load a {kib} dashboard that accesses
+data in an index that you are not authorized to view, you get an error that
+indicates the index does not exist. The {security-features} do not currently
+provide a way to control which users can load which dashboards.
-To use {kib} with {security}:
+To use {kib} with {security-features}:
. {ref}/configuring-security.html[Configure security in {es}].
@@ -38,8 +38,8 @@ elasticsearch.password: "kibanapassword"
The {kib} server submits requests as this user to access the cluster monitoring
APIs and the `.kibana` index. The server does _not_ need access to user indices.
-The password for the built-in `kibana_system` user is typically set as part of the
-{security} configuration process on {es}. For more information, see
+The password for the built-in `kibana_system` user is typically set as part of
+the security configuration process on {es}. For more information, see
{ref}/built-in-users.html[Built-in users].
--
@@ -53,7 +53,7 @@ as the encryption key.
xpack.security.encryptionKey: "something_at_least_32_characters"
--------------------------------------------------------------------------------
-For more information, see <>.
+For more information, see <>.
--
. Optional: Set a timeout to expire idle sessions. By default, a session stays
diff --git a/examples/README.md b/examples/README.asciidoc
similarity index 68%
rename from examples/README.md
rename to examples/README.asciidoc
index 2b214a8d1eb52..d33c5e825ce12 100644
--- a/examples/README.md
+++ b/examples/README.asciidoc
@@ -1,7 +1,9 @@
-## Example plugins
+[[example-plugins]]
+== Example plugins
This folder contains example plugins. To run the plugins in this folder, use the `--run-examples` flag, via
-```
+[source,bash]
+----
yarn start --run-examples
-```
+----
diff --git a/package.json b/package.json
index 541fcc46a3d6e..2f3f95854df04 100644
--- a/package.json
+++ b/package.json
@@ -125,7 +125,7 @@
"@elastic/apm-rum": "^5.2.0",
"@elastic/charts": "19.8.1",
"@elastic/datemath": "5.0.3",
- "@elastic/elasticsearch": "7.8.0",
+ "@elastic/elasticsearch": "7.9.0-rc.2",
"@elastic/ems-client": "7.9.3",
"@elastic/eui": "26.3.1",
"@elastic/filesaver": "1.1.2",
@@ -137,7 +137,6 @@
"@hapi/good-squeeze": "5.2.1",
"@hapi/wreck": "^15.0.2",
"@kbn/analytics": "1.0.0",
- "@kbn/babel-code-parser": "1.0.0",
"@kbn/babel-preset": "1.0.0",
"@kbn/config-schema": "1.0.0",
"@kbn/i18n": "1.0.0",
@@ -323,7 +322,7 @@
"@types/browserslist-useragent": "^3.0.0",
"@types/chance": "^1.0.0",
"@types/cheerio": "^0.22.10",
- "@types/chromedriver": "^2.38.0",
+ "@types/chromedriver": "^81.0.0",
"@types/classnames": "^2.2.9",
"@types/color": "^3.0.0",
"@types/d3": "^3.5.43",
@@ -412,7 +411,7 @@
"chai": "3.5.0",
"chance": "1.0.18",
"cheerio": "0.22.0",
- "chromedriver": "^83.0.0",
+ "chromedriver": "^84.0.0",
"classnames": "2.2.6",
"dedent": "^0.7.0",
"delete-empty": "^2.0.0",
diff --git a/packages/kbn-babel-code-parser/.babelrc b/packages/kbn-babel-code-parser/.babelrc
deleted file mode 100644
index 7da72d1779128..0000000000000
--- a/packages/kbn-babel-code-parser/.babelrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "presets": ["@kbn/babel-preset/node_preset"]
-}
diff --git a/packages/kbn-babel-code-parser/README.md b/packages/kbn-babel-code-parser/README.md
deleted file mode 100755
index f99d01541ee22..0000000000000
--- a/packages/kbn-babel-code-parser/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# @kbn/babel-code-parser
-
-Simple abstraction over the `@babel/parser` and the `@babel/traverse` in order
-to build a code parser on top.
-
-We have two main functions `parseSingleFile` (sync and sync version) and the
-`parseEntries` (only async version). The first one just parse one entry file
-and the second one parses recursively all the files from a list of
-start entry points.
-
-Then we have `visitors` and `strategies`. The first ones are basically the
-`visitors` to use into the ast from the `@babel/traverse`. They are the only
-way to collect info when using the `parseSingleFile`. The `strategies` are
-meant to be used with the `parseEntries` and configures the info we want
-to collect from our parsed code. After each loop, one per entry file, the
-`parseEntries` method will call the given `strategy` expecting that
-`strategy` would call the desired visitors, assemble the important
-information to collect and adds them to the final results.
-
diff --git a/packages/kbn-babel-code-parser/package.json b/packages/kbn-babel-code-parser/package.json
deleted file mode 100755
index 6f42c086ecaab..0000000000000
--- a/packages/kbn-babel-code-parser/package.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "name": "@kbn/babel-code-parser",
- "description": "babel code parser for Kibana",
- "private": true,
- "version": "1.0.0",
- "main": "./target/index.js",
- "license": "Apache-2.0",
- "repository": {
- "type": "git",
- "url": "https://github.com/elastic/kibana/tree/master/packages/kbn-babel-code-parser"
- },
- "scripts": {
- "build": "babel src --out-dir target",
- "kbn:bootstrap": "yarn build --quiet",
- "kbn:watch": "yarn build --watch"
- },
- "devDependencies": {
- "@babel/cli": "^7.10.1"
- },
- "dependencies": {
- "@kbn/babel-preset": "1.0.0",
- "@babel/parser": "^7.10.2",
- "@babel/traverse": "^7.10.1",
- "lodash": "^4.17.15"
- }
-}
diff --git a/packages/kbn-babel-code-parser/src/can_require.js b/packages/kbn-babel-code-parser/src/can_require.js
deleted file mode 100644
index b410611237766..0000000000000
--- a/packages/kbn-babel-code-parser/src/can_require.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export function canRequire(entry, cwd = require.resolve.paths(entry) || []) {
- try {
- // We will try to test if we can resolve
- // this entry through the require.resolve
- // setting as the start looking path the
- // given cwd. That cwd variable could be
- // a path or an array of paths
- // from where Require.resolve will keep
- // looking recursively as normal starting
- // from those locations.
- return require.resolve(entry, {
- paths: [].concat(cwd),
- });
- } catch (e) {
- return false;
- }
-}
diff --git a/packages/kbn-babel-code-parser/src/code_parser.js b/packages/kbn-babel-code-parser/src/code_parser.js
deleted file mode 100644
index 91927780363ac..0000000000000
--- a/packages/kbn-babel-code-parser/src/code_parser.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { canRequire } from './can_require';
-import { readFile, readFileSync } from 'fs';
-import { extname } from 'path';
-import { promisify } from 'util';
-import * as parser from '@babel/parser';
-import traverse from '@babel/traverse';
-import * as babelParserOptions from '@kbn/babel-preset/common_babel_parser_options';
-
-const read = promisify(readFile);
-
-function _cannotParseFile(filePath) {
- return extname(filePath) !== '.js';
-}
-
-function _parseAndTraverseFileContent(fileContent, visitorsGenerator) {
- const results = [];
-
- // Parse and get the code AST
- // All the babel parser plugins
- // were enabled
- const ast = parser.parse(fileContent, babelParserOptions);
-
- // Loop through the code AST with
- // the defined visitors
- traverse(ast, visitorsGenerator(results));
-
- return results;
-}
-
-export async function parseSingleFile(filePath, visitorsGenerator) {
- // Don't parse any other files than .js ones
- if (_cannotParseFile(filePath)) {
- return [];
- }
-
- // Read the file
- const content = await read(filePath, { encoding: 'utf8' });
-
- // return the results found on parse and traverse
- // the file content with the given visitors
- return _parseAndTraverseFileContent(content, visitorsGenerator);
-}
-
-export function parseSingleFileSync(filePath, visitorsGenerator) {
- // Don't parse any other files than .js ones
- if (_cannotParseFile(filePath)) {
- return [];
- }
-
- // Read the file
- const content = readFileSync(filePath, { encoding: 'utf8' });
-
- // return the results found on parse and traverse
- // the file content with the given visitors
- return _parseAndTraverseFileContent(content, visitorsGenerator);
-}
-
-export async function parseEntries(cwd, entries, strategy, results, wasParsed = {}) {
- // Assure that we always have a cwd
- const sanitizedCwd = cwd || process.cwd();
-
- // Test each entry against canRequire function
- const entriesQueue = entries.map((entry) => canRequire(entry));
-
- while (entriesQueue.length) {
- // Get the first element in the queue as
- // select it as our current entry to parse
- const mainEntry = entriesQueue.shift();
-
- // Avoid parse the current entry if it is not valid
- // or it was already parsed
- if (typeof mainEntry !== 'string' || wasParsed[mainEntry]) {
- continue;
- }
-
- // Find new entries and adds them to the end of the queue
- entriesQueue.push(
- ...(await strategy(sanitizedCwd, parseSingleFile, mainEntry, wasParsed, results))
- );
-
- // Mark the current main entry as already parsed
- wasParsed[mainEntry] = true;
- }
-
- return results;
-}
diff --git a/packages/kbn-babel-code-parser/src/index.js b/packages/kbn-babel-code-parser/src/index.js
deleted file mode 100644
index 70e4eb18068b0..0000000000000
--- a/packages/kbn-babel-code-parser/src/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export { dependenciesParseStrategy } from './strategies';
-export { dependenciesVisitorsGenerator } from './visitors';
-export { parseSingleFile, parseSingleFileSync, parseEntries } from './code_parser';
diff --git a/packages/kbn-babel-code-parser/src/strategies.js b/packages/kbn-babel-code-parser/src/strategies.js
deleted file mode 100644
index 2369692ad434b..0000000000000
--- a/packages/kbn-babel-code-parser/src/strategies.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { canRequire } from './can_require';
-import { dependenciesVisitorsGenerator } from './visitors';
-import { dirname, isAbsolute, resolve } from 'path';
-import { builtinModules } from 'module';
-
-export function _calculateTopLevelDependency(inputDep, outputDep = '') {
- // The path separator will be always the forward slash
- // as at this point we only have the found entries into
- // the provided source code entries where we just use it
- const pathSeparator = '/';
- const depSplitPaths = inputDep.split(pathSeparator);
- const firstPart = depSplitPaths.shift();
- const outputDepFirstArgAppend = outputDep ? pathSeparator : '';
-
- outputDep += `${outputDepFirstArgAppend}${firstPart}`;
-
- // In case our dependency isn't started by @
- // we are already done and we can return the
- // dependency value we already have
- if (firstPart.charAt(0) !== '@') {
- return outputDep;
- }
-
- // Otherwise we need to keep constructing the dependency
- // value because dependencies starting with @ points to
- // folders of dependencies. For example, in case we found
- // dependencies values with '@the-deps/a' and '@the-deps/a/b'
- // we don't want to map it to '@the-deps' but also to @'the-deps/a'
- // because inside '@the-deps' we can also have '@the-dep/b'
- return _calculateTopLevelDependency(depSplitPaths.join(pathSeparator), outputDep);
-}
-
-export async function dependenciesParseStrategy(
- cwd,
- parseSingleFile,
- mainEntry,
- wasParsed,
- results
-) {
- // Get dependencies from a single file and filter
- // out node native modules from the result
- const dependencies = (await parseSingleFile(mainEntry, dependenciesVisitorsGenerator)).filter(
- (dep) => !builtinModules.includes(dep)
- );
-
- // Return the list of all the new entries found into
- // the current mainEntry that we could use to look for
- // new dependencies
- return dependencies.reduce((filteredEntries, entry) => {
- const absEntryPath = resolve(cwd, dirname(mainEntry), entry);
-
- // NOTE: cwd for following canRequires is absEntryPath
- // because we should start looking from there
- const requiredPath = canRequire(absEntryPath, absEntryPath);
- const requiredRelativePath = canRequire(entry, absEntryPath);
-
- const isRelativeFile = !isAbsolute(entry);
- const isNodeModuleDep = isRelativeFile && !requiredPath && requiredRelativePath;
- const isNewEntry = isRelativeFile && requiredPath;
-
- // If it is a node_module add it to the results and also
- // add the resolved path for the node_module main file
- // as an entry point to look for dependencies it was
- // not already parsed
- if (isNodeModuleDep) {
- // Save the result as the top level dependency
- results[_calculateTopLevelDependency(entry)] = true;
-
- if (!wasParsed[requiredRelativePath]) {
- filteredEntries.push(requiredRelativePath);
- }
- }
-
- // If a new, not yet parsed, relative entry were found
- // add it to the list of entries to be parsed
- if (isNewEntry && !wasParsed[requiredPath]) {
- if (!wasParsed[requiredPath]) {
- filteredEntries.push(requiredPath);
- }
- }
-
- return filteredEntries;
- }, []);
-}
diff --git a/packages/kbn-babel-code-parser/src/strategies.test.js b/packages/kbn-babel-code-parser/src/strategies.test.js
deleted file mode 100644
index e61c784cdcd54..0000000000000
--- a/packages/kbn-babel-code-parser/src/strategies.test.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { readFile } from 'fs';
-import { canRequire } from './can_require';
-import { parseSingleFile } from './code_parser';
-import { _calculateTopLevelDependency, dependenciesParseStrategy } from './strategies';
-
-jest.mock('./can_require', () => ({
- canRequire: jest.fn(),
-}));
-
-jest.mock('fs', () => ({
- readFile: jest.fn(),
-}));
-
-const mockCwd = '/tmp/project/dir/';
-
-describe('Code Parser Strategies', () => {
- it('should calculate the top level dependencies correctly', () => {
- const plainDep = 'dep1/file';
- const foldedDep = '@kbn/es/file';
- const otherFoldedDep = '@kbn/es';
-
- expect(_calculateTopLevelDependency(plainDep)).toEqual('dep1');
- expect(_calculateTopLevelDependency(foldedDep)).toEqual('@kbn/es');
- expect(_calculateTopLevelDependency(otherFoldedDep)).toEqual('@kbn/es');
- });
-
- it('should exclude native modules', async () => {
- readFile.mockImplementationOnce((path, options, cb) => {
- cb(null, `require('fs')`);
- });
-
- const results = [];
- await dependenciesParseStrategy(mockCwd, parseSingleFile, 'dep1/file.js', {}, results);
-
- expect(results.length).toBe(0);
- });
-
- it('should return a dep from_modules', async () => {
- readFile.mockImplementationOnce((path, options, cb) => {
- cb(null, `require('dep_from_node_modules')`);
- });
-
- canRequire.mockImplementation((entry, cwd) => {
- if (entry === `${cwd}dep1/dep_from_node_modules`) {
- return false;
- }
-
- if (entry === 'dep_from_node_modules') {
- return `${mockCwd}node_modules/dep_from_node_modules/index.js`;
- }
- });
-
- const results = await dependenciesParseStrategy(
- mockCwd,
- parseSingleFile,
- 'dep1/file.js',
- {},
- {}
- );
- expect(results[0]).toBe(`${mockCwd}node_modules/dep_from_node_modules/index.js`);
- });
-
- it('should return a relative dep file', async () => {
- readFile.mockImplementationOnce((path, options, cb) => {
- cb(null, `require('./relative_dep')`);
- });
-
- canRequire.mockImplementation((entry) => {
- if (entry === `${mockCwd}dep1/relative_dep`) {
- return `${entry}/index.js`;
- }
-
- return false;
- });
-
- const results = await dependenciesParseStrategy(
- mockCwd,
- parseSingleFile,
- 'dep1/file.js',
- {},
- {}
- );
- expect(results[0]).toBe(`${mockCwd}dep1/relative_dep/index.js`);
- });
-
- afterAll(() => {
- jest.clearAllMocks();
- });
-});
diff --git a/packages/kbn-babel-code-parser/src/visitors.js b/packages/kbn-babel-code-parser/src/visitors.js
deleted file mode 100644
index b159848d424fa..0000000000000
--- a/packages/kbn-babel-code-parser/src/visitors.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/* eslint-disable @kbn/eslint/require-license-header */
-
-import { matches } from 'lodash';
-
-/* @notice
- *
- * This product has relied on ASTExplorer that is licensed under MIT.
- */
-export function dependenciesVisitorsGenerator(dependenciesAcc) {
- return (() => {
- // This was built with help on an ast explorer and some ESTree docs
- // like the babel parser ast spec and the main docs for the Esprima
- // which is a complete and useful docs for the ESTree spec.
- //
- // https://astexplorer.net
- // https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md
- // https://esprima.readthedocs.io/en/latest/syntax-tree-format.html
- // https://github.com/estree/estree
- return {
- // Visitors to traverse and found dependencies
- // raw values on require + require.resolve
- CallExpression: ({ node }) => {
- // AST check for require expressions
- const isRequire = (node) => {
- return matches({
- callee: {
- type: 'Identifier',
- name: 'require',
- },
- })(node);
- };
-
- // AST check for require.resolve expressions
- const isRequireResolve = (node) => {
- return matches({
- callee: {
- type: 'MemberExpression',
- object: {
- type: 'Identifier',
- name: 'require',
- },
- property: {
- type: 'Identifier',
- name: 'resolve',
- },
- },
- })(node);
- };
-
- // Get string values inside the expressions
- // whether they are require or require.resolve
- if (isRequire(node) || isRequireResolve(node)) {
- const nodeArguments = node.arguments;
- const reqArg = Array.isArray(nodeArguments) ? nodeArguments.shift() : null;
-
- if (!reqArg) {
- return;
- }
-
- if (reqArg.type === 'StringLiteral') {
- dependenciesAcc.push(reqArg.value);
- }
- }
- },
- // Visitors to traverse and found dependencies
- // raw values on import
- ImportDeclaration: ({ node }) => {
- // AST check for supported import expressions
- const isImport = (node) => {
- return matches({
- type: 'ImportDeclaration',
- source: {
- type: 'StringLiteral',
- },
- })(node);
- };
-
- // Get string values from import expressions
- if (isImport(node)) {
- const importSource = node.source;
- dependenciesAcc.push(importSource.value);
- }
- },
- // Visitors to traverse and found dependencies
- // raw values on export from
- ExportNamedDeclaration: ({ node }) => {
- // AST check for supported export from expressions
- const isExportFrom = (node) => {
- return matches({
- type: 'ExportNamedDeclaration',
- source: {
- type: 'StringLiteral',
- },
- })(node);
- };
-
- // Get string values from export from expressions
- if (isExportFrom(node)) {
- const exportFromSource = node.source;
- dependenciesAcc.push(exportFromSource.value);
- }
- },
- // Visitors to traverse and found dependencies
- // raw values on export * from
- ExportAllDeclaration: ({ node }) => {
- // AST check for supported export * from expressions
- const isExportAllFrom = (node) => {
- return matches({
- type: 'ExportAllDeclaration',
- source: {
- type: 'StringLiteral',
- },
- })(node);
- };
-
- // Get string values from export * from expressions
- if (isExportAllFrom(node)) {
- const exportAllFromSource = node.source;
- dependenciesAcc.push(exportAllFromSource.value);
- }
- },
- };
- })();
-}
diff --git a/packages/kbn-babel-code-parser/src/visitors.test.js b/packages/kbn-babel-code-parser/src/visitors.test.js
deleted file mode 100644
index d2704fa9dfb72..0000000000000
--- a/packages/kbn-babel-code-parser/src/visitors.test.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import * as parser from '@babel/parser';
-import traverse from '@babel/traverse';
-import { dependenciesVisitorsGenerator } from './visitors';
-
-const visitorsApplier = (code) => {
- const result = [];
- traverse(
- parser.parse(code, {
- sourceType: 'unambiguous',
- plugins: ['exportDefaultFrom'],
- }),
- dependenciesVisitorsGenerator(result)
- );
- return result;
-};
-
-describe('Code Parser Visitors', () => {
- it('should get values from require', () => {
- const rawCode = `/*foo*/require('dep1'); const bar = 1;`;
- const foundDeps = visitorsApplier(rawCode);
- expect(foundDeps[0] === 'dep1');
- });
-
- it('should get values from require.resolve', () => {
- const rawCode = `/*foo*/require.resolve('dep2'); const bar = 1;`;
- const foundDeps = visitorsApplier(rawCode);
- expect(foundDeps[0] === 'dep2');
- });
-
- it('should get values from import', () => {
- const rawCode = `/*foo*/import dep1 from 'dep1'; import dep2 from 'dep2';const bar = 1;`;
- const foundDeps = visitorsApplier(rawCode);
- expect(foundDeps[0] === 'dep1');
- expect(foundDeps[1] === 'dep2');
- });
-
- it('should get values from export from', () => {
- const rawCode = `/*foo*/export dep1 from 'dep1'; import dep2 from 'dep2';const bar = 1;`;
- const foundDeps = visitorsApplier(rawCode);
- expect(foundDeps[0] === 'dep1');
- });
-
- it('should get values from export * from', () => {
- const rawCode = `/*foo*/export * from 'dep1'; export dep2 from 'dep2';const bar = 1;`;
- const foundDeps = visitorsApplier(rawCode);
- expect(foundDeps[0] === 'dep1');
- expect(foundDeps[1] === 'dep2');
- });
-});
diff --git a/packages/kbn-babel-code-parser/yarn.lock b/packages/kbn-babel-code-parser/yarn.lock
deleted file mode 120000
index 3f82ebc9cdbae..0000000000000
--- a/packages/kbn-babel-code-parser/yarn.lock
+++ /dev/null
@@ -1 +0,0 @@
-../../yarn.lock
\ No newline at end of file
diff --git a/packages/kbn-dev-utils/src/index.ts b/packages/kbn-dev-utils/src/index.ts
index 3e9e6238df9dc..582526f939e42 100644
--- a/packages/kbn-dev-utils/src/index.ts
+++ b/packages/kbn-dev-utils/src/index.ts
@@ -33,9 +33,9 @@ export {
KBN_P12_PATH,
KBN_P12_PASSWORD,
} from './certs';
-export { run, createFailError, createFlagError, combineErrors, isFailError, Flags } from './run';
export { REPO_ROOT } from './repo_root';
export { KbnClient } from './kbn_client';
+export * from './run';
export * from './axios';
export * from './stdio';
export * from './ci_stats_reporter';
diff --git a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts
index f3f8817299bb1..f0f799862e24e 100644
--- a/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts
+++ b/packages/kbn-dev-utils/src/plugin_list/generate_plugin_list.ts
@@ -54,7 +54,7 @@ NOTE:
////
[[code-exploration]]
-=== Exploring Kibana code
+== Exploring Kibana code
The goals of our folder heirarchy are:
@@ -71,14 +71,14 @@ To that aim, we strive to:
[discrete]
[[kibana-services-applications]]
-==== Services and Applications
+=== Services and Applications
[discrete]
-===== src/plugins
+==== src/plugins
${Array.from(printPlugins(ossPlugins)).join('\n')}
[discrete]
-===== x-pack/plugins
+==== x-pack/plugins
${Array.from(printPlugins(xpackPlugins)).join('\n')}
`;
}
diff --git a/packages/kbn-dev-utils/src/run/cleanup.ts b/packages/kbn-dev-utils/src/run/cleanup.ts
new file mode 100644
index 0000000000000..84c3bbcb591d2
--- /dev/null
+++ b/packages/kbn-dev-utils/src/run/cleanup.ts
@@ -0,0 +1,94 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { inspect } from 'util';
+
+import exitHook from 'exit-hook';
+
+import { ToolingLog } from '../tooling_log';
+import { isFailError } from './fail';
+
+export type CleanupTask = () => void;
+
+export class Cleanup {
+ static setup(log: ToolingLog, helpText: string) {
+ const onUnhandledRejection = (error: any) => {
+ log.error('UNHANDLED PROMISE REJECTION');
+ log.error(
+ error instanceof Error
+ ? error
+ : new Error(`non-Error type rejection value: ${inspect(error)}`)
+ );
+ process.exit(1);
+ };
+
+ process.on('unhandledRejection', onUnhandledRejection);
+
+ const cleanup = new Cleanup(log, helpText, [
+ () => process.removeListener('unhandledRejection', onUnhandledRejection),
+ ]);
+
+ cleanup.add(exitHook(() => cleanup.execute()));
+
+ return cleanup;
+ }
+
+ constructor(
+ private readonly log: ToolingLog,
+ public helpText: string,
+ private readonly tasks: CleanupTask[]
+ ) {}
+
+ add(task: CleanupTask) {
+ this.tasks.push(task);
+ }
+
+ execute(topLevelError?: any) {
+ const tasks = this.tasks.slice(0);
+ this.tasks.length = 0;
+
+ for (const task of tasks) {
+ try {
+ task();
+ } catch (error) {
+ this.onError(error);
+ }
+ }
+
+ if (topLevelError) {
+ this.onError(topLevelError);
+ }
+ }
+
+ private onError(error: any) {
+ if (isFailError(error)) {
+ this.log.error(error.message);
+
+ if (error.showHelp) {
+ this.log.write(this.helpText);
+ }
+
+ process.exitCode = error.exitCode;
+ } else {
+ this.log.error('UNHANDLED ERROR');
+ this.log.error(error);
+ process.exitCode = 1;
+ }
+ }
+}
diff --git a/packages/kbn-dev-utils/src/run/flags.test.ts b/packages/kbn-dev-utils/src/run/flags.test.ts
index c730067a84f46..f6ff70b7abeb4 100644
--- a/packages/kbn-dev-utils/src/run/flags.test.ts
+++ b/packages/kbn-dev-utils/src/run/flags.test.ts
@@ -22,14 +22,12 @@ import { getFlags } from './flags';
it('gets flags correctly', () => {
expect(
getFlags(['-a', '--abc=bcd', '--foo=bar', '--no-bar', '--foo=baz', '--box', 'yes', '-zxy'], {
- flags: {
- boolean: ['x'],
- string: ['abc'],
- alias: {
- x: 'extra',
- },
- allowUnexpected: true,
+ boolean: ['x'],
+ string: ['abc'],
+ alias: {
+ x: 'extra',
},
+ allowUnexpected: true,
})
).toMatchInlineSnapshot(`
Object {
@@ -60,10 +58,8 @@ it('gets flags correctly', () => {
it('guesses types for unexpected flags', () => {
expect(
getFlags(['-abc', '--abc=bcd', '--no-foo', '--bar'], {
- flags: {
- allowUnexpected: true,
- guessTypesForUnexpectedFlags: true,
- },
+ allowUnexpected: true,
+ guessTypesForUnexpectedFlags: true,
})
).toMatchInlineSnapshot(`
Object {
diff --git a/packages/kbn-dev-utils/src/run/flags.ts b/packages/kbn-dev-utils/src/run/flags.ts
index c809a40d8512b..12642bceca15a 100644
--- a/packages/kbn-dev-utils/src/run/flags.ts
+++ b/packages/kbn-dev-utils/src/run/flags.ts
@@ -17,12 +17,9 @@
* under the License.
*/
-import { relative } from 'path';
-
-import dedent from 'dedent';
import getopts from 'getopts';
-import { Options } from './run';
+import { RunOptions } from './run';
export interface Flags {
verbose: boolean;
@@ -36,23 +33,52 @@ export interface Flags {
[key: string]: undefined | boolean | string | string[];
}
-export function getFlags(argv: string[], options: Options): Flags {
+export interface FlagOptions {
+ allowUnexpected?: boolean;
+ guessTypesForUnexpectedFlags?: boolean;
+ help?: string;
+ alias?: { [key: string]: string | string[] };
+ boolean?: string[];
+ string?: string[];
+ default?: { [key: string]: any };
+}
+
+export function mergeFlagOptions(global: FlagOptions = {}, local: FlagOptions = {}): FlagOptions {
+ return {
+ alias: {
+ ...global.alias,
+ ...local.alias,
+ },
+ boolean: [...(global.boolean || []), ...(local.boolean || [])],
+ string: [...(global.string || []), ...(local.string || [])],
+ default: {
+ ...global.alias,
+ ...local.alias,
+ },
+
+ help: local.help,
+
+ allowUnexpected: !!(global.allowUnexpected || local.allowUnexpected),
+ guessTypesForUnexpectedFlags: !!(global.allowUnexpected || local.allowUnexpected),
+ };
+}
+
+export function getFlags(argv: string[], flagOptions: RunOptions['flags'] = {}): Flags {
const unexpectedNames = new Set();
- const flagOpts = options.flags || {};
const { verbose, quiet, silent, debug, help, _, ...others } = getopts(argv, {
- string: flagOpts.string,
- boolean: [...(flagOpts.boolean || []), 'verbose', 'quiet', 'silent', 'debug', 'help'],
+ string: flagOptions.string,
+ boolean: [...(flagOptions.boolean || []), 'verbose', 'quiet', 'silent', 'debug', 'help'],
alias: {
- ...(flagOpts.alias || {}),
+ ...flagOptions.alias,
v: 'verbose',
},
- default: flagOpts.default,
+ default: flagOptions.default,
unknown: (name: string) => {
unexpectedNames.add(name);
- return flagOpts.guessTypesForUnexpectedFlags;
+ return !!flagOptions.guessTypesForUnexpectedFlags;
},
- } as any);
+ });
const unexpected: string[] = [];
for (const unexpectedName of unexpectedNames) {
@@ -119,32 +145,3 @@ export function getFlags(argv: string[], options: Options): Flags {
...others,
};
}
-
-export function getHelp(options: Options) {
- const usage = options.usage || `node ${relative(process.cwd(), process.argv[1])}`;
-
- const optionHelp = (
- dedent(options?.flags?.help || '') +
- '\n' +
- dedent`
- --verbose, -v Log verbosely
- --debug Log debug messages (less than verbose)
- --quiet Only log errors
- --silent Don't log anything
- --help Show this message
- `
- )
- .split('\n')
- .filter(Boolean)
- .join('\n ');
-
- return `
- ${usage}
-
- ${dedent(options.description || 'Runs a dev task')
- .split('\n')
- .join('\n ')}
-
- Options:
- ${optionHelp + '\n\n'}`;
-}
diff --git a/packages/kbn-dev-utils/src/run/help.test.ts b/packages/kbn-dev-utils/src/run/help.test.ts
new file mode 100644
index 0000000000000..27be7ad28b81a
--- /dev/null
+++ b/packages/kbn-dev-utils/src/run/help.test.ts
@@ -0,0 +1,199 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { getCommandLevelHelp, getHelp, getHelpForAllCommands } from './help';
+import { Command } from './run_with_commands';
+
+const fooCommand: Command = {
+ description: `
+ Some thing that we wrote to help us execute things.
+
+ Example:
+
+ foo = bar = baz
+
+ Are you getting it?
+ `,
+ name: 'foo',
+ run: () => {},
+ flags: {
+ help: `
+ --foo Some flag
+ --bar Another flag
+ Secondary info
+ --baz, -b Hey hello
+ `,
+ },
+ usage: 'foo [...names]',
+};
+
+const barCommand: Command = {
+ description: `
+ Some other thing that we wrote to help us execute things.
+ `,
+ name: 'bar',
+ run: () => {},
+ flags: {
+ help: `
+ --baz, -b Hey hello
+ `,
+ },
+ usage: 'bar [...names]',
+};
+
+describe('getHelp()', () => {
+ it('returns the expected output', () => {
+ expect(
+ getHelp({
+ description: fooCommand.description,
+ flagHelp: fooCommand.flags?.help,
+ usage: `
+ node scripts/foo --bar --baz
+ `,
+ })
+ ).toMatchInlineSnapshot(`
+ "
+ node scripts/foo --bar --baz
+
+ Some thing that we wrote to help us execute things.
+
+ Example:
+
+ foo = bar = baz
+
+ Are you getting it?
+
+ Options:
+ --foo Some flag
+ --bar Another flag
+ Secondary info
+ --baz, -b Hey hello
+ --verbose, -v Log verbosely
+ --debug Log debug messages (less than verbose)
+ --quiet Only log errors
+ --silent Don't log anything
+ --help Show this message
+
+ "
+ `);
+ });
+});
+
+describe('getCommandLevelHelp()', () => {
+ it('returns the expected output', () => {
+ expect(
+ getCommandLevelHelp({
+ command: fooCommand,
+ globalFlagHelp: `
+ --global-flag some flag that applies to all commands
+ `,
+ })
+ ).toMatchInlineSnapshot(`
+ "
+ node node_modules/jest-worker/build/workers/processChild.js foo [...names]
+
+ Some thing that we wrote to help us execute things.
+
+ Example:
+
+ foo = bar = baz
+
+ Are you getting it?
+
+ Command-specific options:
+ --foo Some flag
+ --bar Another flag
+ Secondary info
+ --baz, -b Hey hello
+
+ Global options:
+ --global-flag some flag that applies to all commands
+ --verbose, -v Log verbosely
+ --debug Log debug messages (less than verbose)
+ --quiet Only log errors
+ --silent Don't log anything
+ --help Show this message
+
+ To see the help for other commands run:
+ node node_modules/jest-worker/build/workers/processChild.js help [command]
+
+ To see the list of commands run:
+ node node_modules/jest-worker/build/workers/processChild.js --help
+
+ "
+ `);
+ });
+});
+
+describe('getHelpForAllCommands()', () => {
+ it('returns the expected output', () => {
+ expect(
+ getHelpForAllCommands({
+ commands: [fooCommand, barCommand],
+ globalFlagHelp: `
+ --global-flag some flag that applies to all commands
+ `,
+ usage: `
+ node scripts/my_cli
+ `,
+ })
+ ).toMatchInlineSnapshot(`
+ "
+ node scripts/my_cli [command] [...args]
+
+ Runs a dev task
+
+ Commands:
+ foo [...names]
+ Some thing that we wrote to help us execute things.
+
+ Example:
+
+ foo = bar = baz
+
+ Are you getting it?
+
+ Options:
+ --foo Some flag
+ --bar Another flag
+ Secondary info
+ --baz, -b Hey hello
+
+ bar [...names]
+ Some other thing that we wrote to help us execute things.
+
+ Options:
+ --baz, -b Hey hello
+
+
+ Global options:
+ --global-flag some flag that applies to all commands
+ --verbose, -v Log verbosely
+ --debug Log debug messages (less than verbose)
+ --quiet Only log errors
+ --silent Don't log anything
+ --help Show this message
+
+ To show the help information about a specific command run:
+ node scripts/my_cli help [command]
+
+ "
+ `);
+ });
+});
diff --git a/packages/kbn-dev-utils/src/run/help.ts b/packages/kbn-dev-utils/src/run/help.ts
new file mode 100644
index 0000000000000..351c01da5ebe2
--- /dev/null
+++ b/packages/kbn-dev-utils/src/run/help.ts
@@ -0,0 +1,150 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import Path from 'path';
+
+import 'core-js/features/string/repeat';
+import dedent from 'dedent';
+
+import { Command } from './run_with_commands';
+
+const DEFAULT_GLOBAL_USAGE = `node ${Path.relative(process.cwd(), process.argv[1])}`;
+export const GLOBAL_FLAGS = dedent`
+ --verbose, -v Log verbosely
+ --debug Log debug messages (less than verbose)
+ --quiet Only log errors
+ --silent Don't log anything
+ --help Show this message
+`;
+
+export function indent(str: string, depth: number) {
+ const prefix = ' '.repeat(depth);
+ return str
+ .split('\n')
+ .map((line, i) => `${i > 0 ? `\n${prefix}` : ''}${line}`)
+ .join('');
+}
+
+export function joinAndTrimLines(...strings: Array) {
+ return strings.filter(Boolean).join('\n').split('\n').filter(Boolean).join(`\n`);
+}
+
+export function getHelp({
+ description,
+ usage,
+ flagHelp,
+}: {
+ description?: string;
+ usage?: string;
+ flagHelp?: string;
+}) {
+ const optionHelp = joinAndTrimLines(dedent(flagHelp || ''), GLOBAL_FLAGS);
+
+ return `
+ ${dedent(usage || '') || DEFAULT_GLOBAL_USAGE}
+
+ ${indent(dedent(description || 'Runs a dev task'), 2)}
+
+ Options:
+ ${indent(optionHelp, 4)}\n\n`;
+}
+
+export function getCommandLevelHelp({
+ usage,
+ globalFlagHelp,
+ command,
+}: {
+ usage?: string;
+ globalFlagHelp?: string;
+ command: Command;
+}) {
+ const globalUsage = dedent(usage || '') || DEFAULT_GLOBAL_USAGE;
+ const globalHelp = joinAndTrimLines(dedent(globalFlagHelp || ''), GLOBAL_FLAGS);
+
+ const commandUsage = dedent(command.usage || '') || `${command.name} [...args]`;
+ const commandFlags = joinAndTrimLines(dedent(command.flags?.help || ''));
+
+ return `
+ ${globalUsage} ${commandUsage}
+
+ ${indent(dedent(command.description || 'Runs a dev task'), 2)}
+
+ Command-specific options:
+ ${indent(commandFlags, 4)}
+
+ Global options:
+ ${indent(globalHelp, 4)}
+
+ To see the help for other commands run:
+ ${globalUsage} help [command]
+
+ To see the list of commands run:
+ ${globalUsage} --help\n\n`;
+}
+
+export function getHelpForAllCommands({
+ description,
+ usage,
+ globalFlagHelp,
+ commands,
+}: {
+ description?: string;
+ usage?: string;
+ globalFlagHelp?: string;
+ commands: Array>;
+}) {
+ const globalUsage = dedent(usage || '') || DEFAULT_GLOBAL_USAGE;
+ const globalHelp = joinAndTrimLines(dedent(globalFlagHelp || ''), GLOBAL_FLAGS);
+
+ const commandsHelp = commands
+ .map((command) => {
+ const options = command.flags?.help
+ ? '\n' +
+ dedent`
+ Options:
+ ${indent(
+ joinAndTrimLines(dedent(command.flags?.help || '')),
+ ' '.length
+ )}
+ ` +
+ '\n'
+ : '';
+
+ return [
+ dedent(command.usage || '') || command.name,
+ ` ${indent(dedent(command.description || 'Runs a dev task'), 2)}`,
+ ...([indent(options, 2)] || []),
+ ].join('\n');
+ })
+ .join('\n');
+
+ return `
+ ${globalUsage} [command] [...args]
+
+ ${indent(dedent(description || 'Runs a dev task'), 2)}
+
+ Commands:
+ ${indent(commandsHelp, 4)}
+
+ Global options:
+ ${indent(globalHelp, 4)}
+
+ To show the help information about a specific command run:
+ ${globalUsage} help [command]\n\n`;
+}
diff --git a/packages/kbn-dev-utils/src/run/index.ts b/packages/kbn-dev-utils/src/run/index.ts
index 5e1a42deefffb..070ce740bf202 100644
--- a/packages/kbn-dev-utils/src/run/index.ts
+++ b/packages/kbn-dev-utils/src/run/index.ts
@@ -17,6 +17,7 @@
* under the License.
*/
-export { run } from './run';
-export { Flags } from './flags';
-export { createFailError, createFlagError, combineErrors, isFailError } from './fail';
+export * from './run';
+export * from './run_with_commands';
+export * from './flags';
+export * from './fail';
diff --git a/packages/kbn-dev-utils/src/run/run.ts b/packages/kbn-dev-utils/src/run/run.ts
index 029d428565163..2a844bcbc27eb 100644
--- a/packages/kbn-dev-utils/src/run/run.ts
+++ b/packages/kbn-dev-utils/src/run/run.ts
@@ -17,48 +17,37 @@
* under the License.
*/
-import { inspect } from 'util';
-
-// @ts-ignore @types are outdated and module is super simple
-import exitHook from 'exit-hook';
-
import { pickLevelFromFlags, ToolingLog, LogLevel } from '../tooling_log';
-import { createFlagError, isFailError } from './fail';
-import { Flags, getFlags, getHelp } from './flags';
+import { createFlagError } from './fail';
+import { Flags, getFlags, FlagOptions } from './flags';
import { ProcRunner, withProcRunner } from '../proc_runner';
+import { getHelp } from './help';
+import { CleanupTask, Cleanup } from './cleanup';
-type CleanupTask = () => void;
-type RunFn = (args: {
+export interface RunContext {
log: ToolingLog;
flags: Flags;
procRunner: ProcRunner;
addCleanupTask: (task: CleanupTask) => void;
-}) => Promise | void;
+}
+export type RunFn = (context: RunContext) => Promise | void;
-export interface Options {
+export interface RunOptions {
usage?: string;
description?: string;
log?: {
defaultLevel?: LogLevel;
};
- flags?: {
- allowUnexpected?: boolean;
- guessTypesForUnexpectedFlags?: boolean;
- help?: string;
- alias?: { [key: string]: string | string[] };
- boolean?: string[];
- string?: string[];
- default?: { [key: string]: any };
- };
+ flags?: FlagOptions;
}
-export async function run(fn: RunFn, options: Options = {}) {
- const flags = getFlags(process.argv.slice(2), options);
-
- if (flags.help) {
- process.stderr.write(getHelp(options));
- process.exit(1);
- }
+export async function run(fn: RunFn, options: RunOptions = {}) {
+ const flags = getFlags(process.argv.slice(2), options.flags);
+ const helpText = getHelp({
+ description: options.description,
+ usage: options.usage,
+ flagHelp: options.flags?.help,
+ });
const log = new ToolingLog({
level: pickLevelFromFlags(flags, {
@@ -67,67 +56,33 @@ export async function run(fn: RunFn, options: Options = {}) {
writeTo: process.stdout,
});
- process.on('unhandledRejection', (error) => {
- log.error('UNHANDLED PROMISE REJECTION');
- log.error(
- error instanceof Error
- ? error
- : new Error(`non-Error type rejection value: ${inspect(error)}`)
- );
- process.exit(1);
- });
-
- const handleErrorWithoutExit = (error: any) => {
- if (isFailError(error)) {
- log.error(error.message);
-
- if (error.showHelp) {
- log.write(getHelp(options));
- }
-
- process.exitCode = error.exitCode;
- } else {
- log.error('UNHANDLED ERROR');
- log.error(error);
- process.exitCode = 1;
- }
- };
-
- const doCleanup = () => {
- const tasks = cleanupTasks.slice(0);
- cleanupTasks.length = 0;
+ if (flags.help) {
+ log.write(helpText);
+ process.exit();
+ }
- for (const task of tasks) {
- try {
- task();
- } catch (error) {
- handleErrorWithoutExit(error);
- }
- }
- };
+ const cleanup = Cleanup.setup(log, helpText);
- const unhookExit: CleanupTask = exitHook(doCleanup);
- const cleanupTasks: CleanupTask[] = [unhookExit];
+ if (!options.flags?.allowUnexpected && flags.unexpected.length) {
+ const error = createFlagError(`Unknown flag(s) "${flags.unexpected.join('", "')}"`);
+ cleanup.execute(error);
+ return;
+ }
try {
- if (!options.flags?.allowUnexpected && flags.unexpected.length) {
- throw createFlagError(`Unknown flag(s) "${flags.unexpected.join('", "')}"`);
- }
-
- try {
- await withProcRunner(log, async (procRunner) => {
- await fn({
- log,
- flags,
- procRunner,
- addCleanupTask: (task: CleanupTask) => cleanupTasks.push(task),
- });
+ await withProcRunner(log, async (procRunner) => {
+ await fn({
+ log,
+ flags,
+ procRunner,
+ addCleanupTask: cleanup.add.bind(cleanup),
});
- } finally {
- doCleanup();
- }
+ });
} catch (error) {
- handleErrorWithoutExit(error);
+ cleanup.execute(error);
+ // process.exitCode is set by `cleanup` when necessary
process.exit();
+ } finally {
+ cleanup.execute();
}
}
diff --git a/packages/kbn-dev-utils/src/run/run_with_commands.test.ts b/packages/kbn-dev-utils/src/run/run_with_commands.test.ts
new file mode 100644
index 0000000000000..eb7708998751c
--- /dev/null
+++ b/packages/kbn-dev-utils/src/run/run_with_commands.test.ts
@@ -0,0 +1,77 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { RunWithCommands } from './run_with_commands';
+import { ToolingLog, ToolingLogCollectingWriter } from '../tooling_log';
+import { ProcRunner } from '../proc_runner';
+
+const testLog = new ToolingLog();
+const testLogWriter = new ToolingLogCollectingWriter();
+testLog.setWriters([testLogWriter]);
+
+const testCli = new RunWithCommands({
+ usage: 'node scripts/test_cli [...options]',
+ description: 'test cli',
+ extendContext: async () => {
+ return {
+ extraContext: true,
+ };
+ },
+ globalFlags: {
+ boolean: ['some-bool'],
+ help: `
+ --some-bool description
+ `,
+ },
+});
+
+beforeEach(() => {
+ process.argv = ['node', 'scripts/test_cli', 'foo', '--some-bool'];
+ jest.clearAllMocks();
+});
+
+it('extends the context using extendContext()', async () => {
+ const context: any = await new Promise((resolve) => {
+ testCli.command({ name: 'foo', description: 'some command', run: resolve }).execute();
+ });
+
+ expect(context).toEqual({
+ log: expect.any(ToolingLog),
+ flags: expect.any(Object),
+ addCleanupTask: expect.any(Function),
+ procRunner: expect.any(ProcRunner),
+ extraContext: true,
+ });
+
+ expect(context.flags).toMatchInlineSnapshot(`
+ Object {
+ "_": Array [
+ "foo",
+ ],
+ "debug": false,
+ "help": false,
+ "quiet": false,
+ "silent": false,
+ "some-bool": true,
+ "unexpected": Array [],
+ "v": false,
+ "verbose": false,
+ }
+ `);
+});
diff --git a/packages/kbn-dev-utils/src/run/run_with_commands.ts b/packages/kbn-dev-utils/src/run/run_with_commands.ts
new file mode 100644
index 0000000000000..9fb069e4b2d35
--- /dev/null
+++ b/packages/kbn-dev-utils/src/run/run_with_commands.ts
@@ -0,0 +1,136 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ToolingLog, pickLevelFromFlags } from '../tooling_log';
+import { RunContext, RunOptions } from './run';
+import { getFlags, FlagOptions, mergeFlagOptions } from './flags';
+import { Cleanup } from './cleanup';
+import { getHelpForAllCommands, getCommandLevelHelp } from './help';
+import { createFlagError } from './fail';
+import { withProcRunner } from '../proc_runner';
+
+export type CommandRunFn = (context: RunContext & T) => Promise | void;
+
+export interface Command {
+ name: string;
+ run: CommandRunFn;
+ description: RunOptions['description'];
+ usage?: RunOptions['usage'];
+ flags?: FlagOptions;
+}
+
+export interface RunWithCommandsOptions {
+ log?: RunOptions['log'];
+ description?: RunOptions['description'];
+ usage?: RunOptions['usage'];
+ globalFlags?: FlagOptions;
+ extendContext?(context: RunContext): Promise | T;
+}
+
+export class RunWithCommands {
+ constructor(
+ private readonly options: RunWithCommandsOptions,
+ private readonly commands: Array> = []
+ ) {}
+
+ command(options: Command) {
+ return new RunWithCommands(this.options, this.commands.concat(options));
+ }
+
+ async execute() {
+ const globalFlags = getFlags(process.argv.slice(2), {
+ allowUnexpected: true,
+ });
+
+ const isHelpCommand = globalFlags._[0] === 'help';
+ const commandName = isHelpCommand ? globalFlags._[1] : globalFlags._[0];
+ const command = this.commands.find((c) => c.name === commandName);
+ const log = new ToolingLog({
+ level: pickLevelFromFlags(globalFlags, {
+ default: this.options.log?.defaultLevel,
+ }),
+ writeTo: process.stdout,
+ });
+
+ const globalHelp = getHelpForAllCommands({
+ description: this.options.description,
+ usage: this.options.usage,
+ globalFlagHelp: this.options.globalFlags?.help,
+ commands: this.commands,
+ });
+ const cleanup = Cleanup.setup(log, globalHelp);
+
+ if (!command) {
+ if (globalFlags.help) {
+ log.write(globalHelp);
+ process.exit();
+ }
+
+ const error = createFlagError(
+ commandName ? `unknown command [${commandName}]` : `missing command name`
+ );
+ cleanup.execute(error);
+ process.exit(1);
+ }
+
+ const commandFlagOptions = mergeFlagOptions(this.options.globalFlags, command.flags);
+ const commandFlags = getFlags(process.argv.slice(2), commandFlagOptions);
+ const commandHelp = getCommandLevelHelp({
+ usage: this.options.usage,
+ globalFlagHelp: this.options.globalFlags?.help,
+ command,
+ });
+ cleanup.helpText = commandHelp;
+
+ if (commandFlags.help || isHelpCommand) {
+ cleanup.execute();
+ log.write(commandHelp);
+ process.exit();
+ }
+
+ if (!commandFlagOptions.allowUnexpected && commandFlags.unexpected.length) {
+ cleanup.execute(createFlagError(`Unknown flag(s) "${commandFlags.unexpected.join('", "')}"`));
+ return;
+ }
+
+ try {
+ await withProcRunner(log, async (procRunner) => {
+ const context: RunContext = {
+ log,
+ flags: commandFlags,
+ procRunner,
+ addCleanupTask: cleanup.add,
+ };
+
+ const extendedContext = {
+ ...context,
+ ...(this.options.extendContext ? await this.options.extendContext(context) : ({} as T)),
+ };
+
+ await command.run(extendedContext);
+ });
+ } catch (error) {
+ cleanup.execute(error);
+ // exitCode is set by `cleanup` when necessary
+ process.exit();
+ } finally {
+ cleanup.execute();
+ }
+ }
+}
diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json
index 271b4a3dc661b..f53eb694ec712 100644
--- a/packages/kbn-es/package.json
+++ b/packages/kbn-es/package.json
@@ -5,7 +5,7 @@
"license": "Apache-2.0",
"private": true,
"dependencies": {
- "@elastic/elasticsearch": "^7.4.0",
+ "@elastic/elasticsearch": "7.9.0-rc.1",
"@kbn/dev-utils": "1.0.0",
"abort-controller": "^2.0.3",
"chalk": "^2.4.2",
diff --git a/packages/kbn-plugin-generator/sao_template/sao.js b/packages/kbn-plugin-generator/sao_template/sao.js
index dc4d8a2fc10fb..e5f81a984ee93 100755
--- a/packages/kbn-plugin-generator/sao_template/sao.js
+++ b/packages/kbn-plugin-generator/sao_template/sao.js
@@ -120,6 +120,11 @@ module.exports = function ({ name, targetPath }) {
return !customPath;
},
},
+ generateTsconfig: {
+ type: 'confirm',
+ message: 'Would you like to use a custom tsconfig file?',
+ default: true,
+ },
},
filters: {
'public/**/index.scss': 'generateScss',
@@ -128,6 +133,7 @@ module.exports = function ({ name, targetPath }) {
'translations/**/*': 'generateTranslations',
'i18nrc.json': 'generateTranslations',
'eslintrc.js': 'generateEslint',
+ 'tsconfig.json': 'generateTsconfig',
},
move: {
'eslintrc.js': '.eslintrc.js',
diff --git a/packages/kbn-plugin-generator/sao_template/sao.test.js b/packages/kbn-plugin-generator/sao_template/sao.test.js
index 03d95e12d58da..af243326cff33 100755
--- a/packages/kbn-plugin-generator/sao_template/sao.test.js
+++ b/packages/kbn-plugin-generator/sao_template/sao.test.js
@@ -80,12 +80,14 @@ describe('plugin generator sao integration', () => {
generateApi: true,
generateScss: false,
generateEslint: false,
+ generateTsconfig: false,
});
// check output files
expect(res.fileList).toContain('public/plugin.ts');
expect(res.fileList).not.toContain('public/index.scss');
expect(res.fileList).not.toContain('.eslintrc.js');
+ expect(res.fileList).not.toContain('tsconfig.json');
});
it('plugin package has correct title', async () => {
@@ -136,6 +138,7 @@ describe('plugin generator sao integration', () => {
it('includes dotfiles', async () => {
const res = await sao.mockPrompt(template);
+ expect(res.files['tsconfig.json']).toBeTruthy();
expect(res.files['.eslintrc.js']).toBeTruthy();
expect(res.files['.i18nrc.json']).toBeTruthy();
});
diff --git a/packages/kbn-plugin-generator/sao_template/template/public/components/app.tsx b/packages/kbn-plugin-generator/sao_template/template/public/components/app.tsx
index 7b259a9c5b99d..d75bd2f01ef23 100644
--- a/packages/kbn-plugin-generator/sao_template/template/public/components/app.tsx
+++ b/packages/kbn-plugin-generator/sao_template/template/public/components/app.tsx
@@ -73,7 +73,7 @@ export const <%= upperCamelCaseName %>App = ({ basename, notifications, http, na
<>
-
+
diff --git a/packages/kbn-plugin-generator/sao_template/template/tsconfig.json b/packages/kbn-plugin-generator/sao_template/template/tsconfig.json
new file mode 100644
index 0000000000000..8a3ced743d0fa
--- /dev/null
+++ b/packages/kbn-plugin-generator/sao_template/template/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./target",
+ "skipLibCheck": true
+ },
+ "include": [
+ "index.ts",
+ "common/**/*.ts",
+ "public/**/*.ts",
+ "public/**/*.tsx",
+ "server/**/*.ts",
+ "../../typings/**/*",
+ ],
+ "exclude": []
+}
diff --git a/renovate.json5 b/renovate.json5
index 6424894622c9f..ae32043daaf5f 100644
--- a/renovate.json5
+++ b/renovate.json5
@@ -418,6 +418,14 @@
'@types/has-ansi',
],
},
+ {
+ groupSlug: 'he',
+ groupName: 'he related packages',
+ packageNames: [
+ 'he',
+ '@types/he',
+ ],
+ },
{
groupSlug: 'history',
groupName: 'history related packages',
diff --git a/src/core/public/index.scss b/src/core/public/index.scss
index 87825350b4e98..c2ad2841d5a77 100644
--- a/src/core/public/index.scss
+++ b/src/core/public/index.scss
@@ -2,6 +2,5 @@
@import './chrome/index';
@import './overlays/index';
@import './rendering/index';
+@import './styles/index';
-// Global styles need to be migrated
-@import '../../legacy/ui/public/styles/_legacy/_index';
diff --git a/src/legacy/ui/public/styles/_legacy/components/_ace_overrides.scss b/src/core/public/styles/_ace_overrides.scss
similarity index 96%
rename from src/legacy/ui/public/styles/_legacy/components/_ace_overrides.scss
rename to src/core/public/styles/_ace_overrides.scss
index 2f0bc011f6a5c..30acdbbc80975 100644
--- a/src/legacy/ui/public/styles/_legacy/components/_ace_overrides.scss
+++ b/src/core/public/styles/_ace_overrides.scss
@@ -1,6 +1,3 @@
-@import '@elastic/eui/src/components/call_out/variables';
-@import '@elastic/eui/src/components/call_out/mixins';
-
// SASSTODO: Replace with an EUI editor
// Intentionally not using the EuiCodeBlock colors here because they actually change
// hue from light to dark theme. So some colors would change while others wouldn't.
@@ -181,7 +178,7 @@
}
&.ace_multiselect .ace_selection.ace_start {
- box-shadow: 0 0 3px 0px $euiColorEmptyShade;
+ box-shadow: 0 0 3px 0 $euiColorEmptyShade;
}
.ace_marker-layer .ace_step {
diff --git a/src/core/public/styles/_base.scss b/src/core/public/styles/_base.scss
new file mode 100644
index 0000000000000..9b06b526fc7dd
--- /dev/null
+++ b/src/core/public/styles/_base.scss
@@ -0,0 +1,58 @@
+@import '@elastic/eui/src/components/collapsible_nav/variables';
+// Application Layout
+
+// chrome-context
+// TODO #64541
+// Delete this block
+.chrHeaderWrapper:not(.headerWrapper) .content {
+ display: flex;
+ flex-flow: row nowrap;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+}
+
+.application,
+.app-container {
+ > * {
+ position: relative;
+ }
+}
+
+.application {
+ position: relative;
+ z-index: 0;
+ display: flex;
+ flex-grow: 1;
+ flex-shrink: 0;
+ flex-basis: auto;
+ flex-direction: column;
+
+ > * {
+ flex-shrink: 0;
+ }
+}
+
+// We apply brute force focus states to anything not coming from Eui
+// which has focus states designed at the component level.
+// You can also use "kbn-resetFocusState" to not apply the default focus
+// state. This is useful when you've already hand crafted your own
+// focus states in Kibana.
+:focus {
+ &:not([class^='eui']):not(.kbn-resetFocusState) {
+ @include euiFocusRing;
+ }
+}
+
+// A necessary hack so that the above focus policy doesn't pollute some EUI
+// entrenched inputs.
+.euiComboBox {
+ // :not() specificity needed to override the above
+ input:not([class^='eui']):focus {
+ animation: none !important;
+ }
+}
+
+.euiBody--collapsibleNavIsDocked .euiBottomBar {
+ margin-left: $euiCollapsibleNavWidth;
+}
diff --git a/src/core/public/styles/_index.scss b/src/core/public/styles/_index.scss
new file mode 100644
index 0000000000000..600414402c278
--- /dev/null
+++ b/src/core/public/styles/_index.scss
@@ -0,0 +1,2 @@
+@import './base';
+@import './ace_overrides';
diff --git a/src/core/server/elasticsearch/client/index.ts b/src/core/server/elasticsearch/client/index.ts
index 18e84482024ca..b8125de2ee498 100644
--- a/src/core/server/elasticsearch/client/index.ts
+++ b/src/core/server/elasticsearch/client/index.ts
@@ -22,3 +22,4 @@ export { IScopedClusterClient, ScopedClusterClient } from './scoped_cluster_clie
export { ElasticsearchClientConfig } from './client_config';
export { IClusterClient, ICustomClusterClient, ClusterClient } from './cluster_client';
export { configureClient } from './configure_client';
+export { retryCallCluster, migrationRetryCallCluster } from './retry_call_cluster';
diff --git a/src/core/server/elasticsearch/client/retry_call_cluster.test.ts b/src/core/server/elasticsearch/client/retry_call_cluster.test.ts
new file mode 100644
index 0000000000000..a7177c0b29047
--- /dev/null
+++ b/src/core/server/elasticsearch/client/retry_call_cluster.test.ts
@@ -0,0 +1,283 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { errors } from '@elastic/elasticsearch';
+import { elasticsearchClientMock } from './mocks';
+import { loggingSystemMock } from '../../logging/logging_system.mock';
+import { retryCallCluster, migrationRetryCallCluster } from './retry_call_cluster';
+
+const dummyBody = { foo: 'bar' };
+const createErrorReturn = (err: any) => elasticsearchClientMock.createClientError(err);
+
+describe('retryCallCluster', () => {
+ let client: ReturnType;
+
+ beforeEach(() => {
+ client = elasticsearchClientMock.createElasticSearchClient();
+ });
+
+ it('returns response from ES API call in case of success', async () => {
+ const successReturn = elasticsearchClientMock.createClientResponse({ ...dummyBody });
+
+ client.asyncSearch.get.mockReturnValue(successReturn);
+
+ const result = await retryCallCluster(() => client.asyncSearch.get());
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with `NoLivingConnectionsError`', async () => {
+ const successReturn = elasticsearchClientMock.createClientResponse({ ...dummyBody });
+
+ client.asyncSearch.get
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any))
+ )
+ .mockImplementationOnce(() => successReturn);
+
+ const result = await retryCallCluster(() => client.asyncSearch.get());
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('rejects when ES API calls reject with other errors', async () => {
+ client.ping
+ .mockImplementationOnce(() => createErrorReturn(new Error('unknown error')))
+ .mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
+
+ await expect(retryCallCluster(() => client.ping())).rejects.toMatchInlineSnapshot(
+ `[Error: unknown error]`
+ );
+ });
+
+ it('stops retrying when ES API calls reject with other errors', async () => {
+ client.ping
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any))
+ )
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any))
+ )
+ .mockImplementationOnce(() => createErrorReturn(new Error('unknown error')))
+ .mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
+
+ await expect(retryCallCluster(() => client.ping())).rejects.toMatchInlineSnapshot(
+ `[Error: unknown error]`
+ );
+ });
+});
+
+describe('migrationRetryCallCluster', () => {
+ let client: ReturnType;
+ let logger: ReturnType;
+
+ beforeEach(() => {
+ client = elasticsearchClientMock.createElasticSearchClient();
+ logger = loggingSystemMock.createLogger();
+ });
+
+ const mockClientPingWithErrorBeforeSuccess = (error: any) => {
+ client.ping
+ .mockImplementationOnce(() => createErrorReturn(error))
+ .mockImplementationOnce(() => createErrorReturn(error))
+ .mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
+ };
+
+ it('retries ES API calls that rejects with `NoLivingConnectionsError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.NoLivingConnectionsError('no living connections', {} as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with `ConnectionError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(new errors.ConnectionError('connection error', {} as any));
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with `TimeoutError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(new errors.TimeoutError('timeout error', {} as any));
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with 503 `ResponseError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.ResponseError({
+ statusCode: 503,
+ } as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects 401 `ResponseError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.ResponseError({
+ statusCode: 401,
+ } as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with 403 `ResponseError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.ResponseError({
+ statusCode: 403,
+ } as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with 408 `ResponseError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.ResponseError({
+ statusCode: 408,
+ } as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with 410 `ResponseError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.ResponseError({
+ statusCode: 410,
+ } as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('retries ES API calls that rejects with `snapshot_in_progress_exception` `ResponseError`', async () => {
+ mockClientPingWithErrorBeforeSuccess(
+ new errors.ResponseError({
+ statusCode: 500,
+ body: {
+ error: {
+ type: 'snapshot_in_progress_exception',
+ },
+ },
+ } as any)
+ );
+
+ const result = await migrationRetryCallCluster(() => client.ping(), logger, 1);
+ expect(result.body).toEqual(dummyBody);
+ });
+
+ it('logs only once for each unique error message', async () => {
+ client.ping
+ .mockImplementationOnce(() =>
+ createErrorReturn(
+ new errors.ResponseError({
+ statusCode: 503,
+ } as any)
+ )
+ )
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.ConnectionError('connection error', {} as any))
+ )
+ .mockImplementationOnce(() =>
+ createErrorReturn(
+ new errors.ResponseError({
+ statusCode: 503,
+ } as any)
+ )
+ )
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.ConnectionError('connection error', {} as any))
+ )
+ .mockImplementationOnce(() =>
+ createErrorReturn(
+ new errors.ResponseError({
+ statusCode: 500,
+ body: {
+ error: {
+ type: 'snapshot_in_progress_exception',
+ },
+ },
+ } as any)
+ )
+ )
+ .mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
+
+ await migrationRetryCallCluster(() => client.ping(), logger, 1);
+
+ expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "Unable to connect to Elasticsearch. Error: Response Error",
+ ],
+ Array [
+ "Unable to connect to Elasticsearch. Error: connection error",
+ ],
+ Array [
+ "Unable to connect to Elasticsearch. Error: snapshot_in_progress_exception",
+ ],
+ ]
+ `);
+ });
+
+ it('rejects when ES API calls reject with other errors', async () => {
+ client.ping
+ .mockImplementationOnce(() =>
+ createErrorReturn(
+ new errors.ResponseError({
+ statusCode: 418,
+ body: {
+ error: {
+ type: `I'm a teapot`,
+ },
+ },
+ } as any)
+ )
+ )
+ .mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
+
+ await expect(
+ migrationRetryCallCluster(() => client.ping(), logger, 1)
+ ).rejects.toMatchInlineSnapshot(`[ResponseError: I'm a teapot]`);
+ });
+
+ it('stops retrying when ES API calls reject with other errors', async () => {
+ client.ping
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.TimeoutError('timeout error', {} as any))
+ )
+ .mockImplementationOnce(() =>
+ createErrorReturn(new errors.TimeoutError('timeout error', {} as any))
+ )
+ .mockImplementationOnce(() => createErrorReturn(new Error('unknown error')))
+ .mockImplementationOnce(() => elasticsearchClientMock.createClientResponse({ ...dummyBody }));
+
+ await expect(
+ migrationRetryCallCluster(() => client.ping(), logger, 1)
+ ).rejects.toMatchInlineSnapshot(`[Error: unknown error]`);
+ });
+});
diff --git a/src/core/server/elasticsearch/client/retry_call_cluster.ts b/src/core/server/elasticsearch/client/retry_call_cluster.ts
new file mode 100644
index 0000000000000..1ad039e512215
--- /dev/null
+++ b/src/core/server/elasticsearch/client/retry_call_cluster.ts
@@ -0,0 +1,103 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { defer, throwError, iif, timer } from 'rxjs';
+import { concatMap, retryWhen } from 'rxjs/operators';
+import { Logger } from '../../logging';
+
+const retryResponseStatuses = [
+ 503, // ServiceUnavailable
+ 401, // AuthorizationException
+ 403, // AuthenticationException
+ 408, // RequestTimeout
+ 410, // Gone
+];
+
+/**
+ * Retries the provided Elasticsearch API call when a `NoLivingConnectionsError` error is
+ * encountered. The API call will be retried once a second, indefinitely, until
+ * a successful response or a different error is received.
+ *
+ * @example
+ * ```ts
+ * const response = await retryCallCluster(() => client.ping());
+ * ```
+ *
+ * @internal
+ */
+export const retryCallCluster = >(apiCaller: () => T): T => {
+ return defer(() => apiCaller())
+ .pipe(
+ retryWhen((errors) =>
+ errors.pipe(
+ concatMap((error) =>
+ iif(() => error.name === 'NoLivingConnectionsError', timer(1000), throwError(error))
+ )
+ )
+ )
+ )
+ .toPromise() as T;
+};
+
+/**
+ * Retries the provided Elasticsearch API call when an error such as
+ * `AuthenticationException` `NoConnections`, `ConnectionFault`,
+ * `ServiceUnavailable` or `RequestTimeout` are encountered. The API call will
+ * be retried once a second, indefinitely, until a successful response or a
+ * different error is received.
+ *
+ * @example
+ * ```ts
+ * const response = await migrationRetryCallCluster(() => client.ping(), logger);
+ * ```
+ *
+ * @internal
+ */
+export const migrationRetryCallCluster = >(
+ apiCaller: () => T,
+ log: Logger,
+ delay: number = 2500
+): T => {
+ const previousErrors: string[] = [];
+ return defer(() => apiCaller())
+ .pipe(
+ retryWhen((errors) =>
+ errors.pipe(
+ concatMap((error) => {
+ if (!previousErrors.includes(error.message)) {
+ log.warn(`Unable to connect to Elasticsearch. Error: ${error.message}`);
+ previousErrors.push(error.message);
+ }
+ return iif(
+ () =>
+ error.name === 'NoLivingConnectionsError' ||
+ error.name === 'ConnectionError' ||
+ error.name === 'TimeoutError' ||
+ (error.name === 'ResponseError' &&
+ retryResponseStatuses.includes(error.statusCode)) ||
+ error?.body?.error?.type === 'snapshot_in_progress_exception',
+ timer(delay),
+ throwError(error)
+ );
+ })
+ )
+ )
+ )
+ .toPromise() as T;
+};
diff --git a/src/core/server/elasticsearch/legacy/retry_call_cluster.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts
index 475a76d406017..1b05cb2bf13cd 100644
--- a/src/core/server/elasticsearch/legacy/retry_call_cluster.ts
+++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts
@@ -53,7 +53,7 @@ export function migrationsRetryCallCluster(
.pipe(
retryWhen((error$) =>
error$.pipe(
- concatMap((error, i) => {
+ concatMap((error) => {
if (!previousErrors.includes(error.message)) {
log.warn(`Unable to connect to Elasticsearch. Error: ${error.message}`);
previousErrors.push(error.message);
@@ -100,7 +100,7 @@ export function retryCallCluster(apiCaller: LegacyAPICaller) {
.pipe(
retryWhen((errors) =>
errors.pipe(
- concatMap((error, i) =>
+ concatMap((error) =>
iif(
() => error instanceof legacyElasticsearch.errors.NoConnections,
timer(1000),
diff --git a/src/dev/build/README.md b/src/dev/build/README.md
index ed8750f6fee56..460ab01794334 100644
--- a/src/dev/build/README.md
+++ b/src/dev/build/README.md
@@ -39,14 +39,3 @@ The majority of this logic is extracted from the grunt build that has existed fo
[lib/build.js]: ./lib/build.js
[build_distributables.js]: ./build_distributables.js
[../tooling_log/tooling_log.js]: ../tooling_log/tooling_log.js
-
-# Client Node Modules Cleaning
-
-We have introduced in our bundle a webpack dll for the client vendor modules in order to improve
-the optimization time both in dev and in production. As for those modules we already have the
-code into the vendors_${chunk_number}.bundle.dll.js we have decided to delete those bundled modules from the
-distributable node_modules folder. However, in order to accomplish this, we need to exclude
-every node_module used in the server side code. This logic is performed
-under `nodejs_modules/clean_client_modules_on_dll_task.js`. In case we need to add any new cli
-or any other piece of server code other than `x-pack` or `core_plugins` we'll need
-to update the globs present on `clean_client_modules_on_dll_task.js` accordingly.
diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js
index 22a348b78dc0a..39a32fff891c2 100644
--- a/src/dev/build/build_distributables.js
+++ b/src/dev/build/build_distributables.js
@@ -22,7 +22,6 @@ import { getConfig, createRunner } from './lib';
import {
BuildKibanaPlatformPluginsTask,
BuildPackagesTask,
- CleanClientModulesOnDLLTask,
CleanEmptyFoldersTask,
CleanExtraBinScriptsTask,
CleanExtraFilesFromModulesTask,
@@ -127,7 +126,6 @@ export async function buildDistributables(options) {
await run(TranspileScssTask);
await run(BuildKibanaPlatformPluginsTask);
await run(OptimizeBuildTask);
- await run(CleanClientModulesOnDLLTask);
await run(CleanTypescriptTask);
await run(CleanExtraFilesFromModulesTask);
await run(CleanEmptyFoldersTask);
diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js
index d96e745c10776..0a3a67313d6a4 100644
--- a/src/dev/build/tasks/index.js
+++ b/src/dev/build/tasks/index.js
@@ -30,7 +30,6 @@ export * from './create_readme_task';
export * from './install_chromium';
export * from './install_dependencies_task';
export * from './license_file_task';
-export * from './nodejs_modules';
export * from './nodejs';
export * from './notice_file_task';
export * from './optimize_task';
diff --git a/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js b/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js
deleted file mode 100644
index 05bfd3ca31a65..0000000000000
--- a/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import {
- getDllEntries,
- cleanDllModuleFromEntryPath,
- writeEmptyFileForDllEntry,
-} from './webpack_dll';
-import { getDependencies } from './get_dependencies';
-import globby from 'globby';
-import normalizePosixPath from 'normalize-path';
-
-export const CleanClientModulesOnDLLTask = {
- description: 'Cleaning client node_modules bundled into the DLL',
-
- async run(config, log, build) {
- const baseDir = normalizePosixPath(build.resolvePath('.'));
- const kbnPkg = config.getKibanaPkg();
- const kbnPkgDependencies = (kbnPkg && kbnPkg.dependencies) || {};
- const kbnWebpackLoaders = Object.keys(kbnPkgDependencies).filter(
- (dep) => !!dep.includes('-loader')
- );
-
- // Define the entry points for the server code in order to
- // start here later looking for the server side dependencies
- const mainCodeEntries = [
- `${baseDir}/src/cli`,
- `${baseDir}/src/cli_keystore`,
- `${baseDir}/src/cli_plugin`,
- `${baseDir}/x-pack`,
- ...kbnWebpackLoaders.map((loader) => `${baseDir}/node_modules/${loader}`),
- ];
- const discoveredLegacyCorePluginEntries = await globby([
- `${baseDir}/src/legacy/core_plugins/*/index.js`,
- `!${baseDir}/src/legacy/core_plugins/**/public`,
- ]);
- const discoveredPluginEntries = await globby([
- `${baseDir}/src/plugins/*/server/index.js`,
- // Small exception to load dynamically discovered functions for timelion plugin
- `${baseDir}/src/plugins/vis_type_timelion/server/*_functions/**/*.js`,
- `!${baseDir}/src/plugins/**/public`,
- ]);
- const discoveredNewPlatformXpackPlugins = await globby([
- `${baseDir}/x-pack/plugins/*/server/index.js`,
- `!${baseDir}/x-pack/plugins/**/public`,
- ]);
-
- // Compose all the needed entries
- const serverEntries = [
- ...mainCodeEntries,
- ...discoveredLegacyCorePluginEntries,
- ...discoveredPluginEntries,
- ...discoveredNewPlatformXpackPlugins,
- ];
-
- // Get the dependencies found searching through the server
- // side code entries that were provided
- const serverDependencies = await getDependencies(baseDir, serverEntries);
-
- // This fulfill a particular exceptional case where
- // we need to keep loading a file from a node_module
- // only used in the front-end like we do when using the file-loader
- // in https://github.com/elastic/kibana/blob/master/x-pack/legacy/plugins/maps/public/connected_components/map/mb/view.js
- //
- // manual list of exception modules
- const manualExceptionModules = ['mapbox-gl'];
-
- // consider the top modules as exceptions as the entry points
- // to look for other exceptions dependent on that one
- const manualExceptionEntries = [
- ...manualExceptionModules.map((module) => `${baseDir}/node_modules/${module}`),
- ];
-
- // dependencies for declared exception modules
- const manualExceptionModulesDependencies = await getDependencies(baseDir, [
- ...manualExceptionEntries,
- ]);
-
- // final list of manual exceptions to add
- const manualExceptions = [...manualExceptionModules, ...manualExceptionModulesDependencies];
-
- // Consider this as our whiteList for the modules we can't delete
- const whiteListedModules = [...serverDependencies, ...kbnWebpackLoaders, ...manualExceptions];
-
- // Resolve the client vendors dll manifest paths
- // excluding the runtime one
- const dllManifestPaths = await globby([
- `${baseDir}/built_assets/dlls/vendors_*.manifest.dll.json`,
- `!${baseDir}/built_assets/dlls/vendors_runtime.manifest.dll.json`,
- ]);
-
- // Get dll entries filtering out the ones
- // from any whitelisted module
- const dllEntries = await getDllEntries(dllManifestPaths, whiteListedModules, baseDir);
-
- for (const relativeEntryPath of dllEntries) {
- const entryPath = `${baseDir}/${relativeEntryPath}`;
-
- if (entryPath.endsWith('package.json')) {
- continue;
- }
-
- // Clean a module included into the dll
- // and then write a blank file for each
- // entry file present into the dll
- await cleanDllModuleFromEntryPath(log, entryPath);
- await writeEmptyFileForDllEntry(entryPath);
- }
- },
-};
diff --git a/src/dev/build/tasks/nodejs_modules/get_dependencies.js b/src/dev/build/tasks/nodejs_modules/get_dependencies.js
deleted file mode 100644
index 5a39448f57d14..0000000000000
--- a/src/dev/build/tasks/nodejs_modules/get_dependencies.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { parseEntries, dependenciesParseStrategy } from '@kbn/babel-code-parser';
-
-export async function getDependencies(cwd, entries) {
- // Return the dependencies retrieve from the
- // provided code entries (sanitized) and
- // parseStrategy (dependencies one)
- return Object.keys(await parseEntries(cwd, entries, dependenciesParseStrategy, {}));
-}
diff --git a/src/dev/build/tasks/nodejs_modules/index.js b/src/dev/build/tasks/nodejs_modules/index.js
deleted file mode 100644
index 1c5392662ad13..0000000000000
--- a/src/dev/build/tasks/nodejs_modules/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export { CleanClientModulesOnDLLTask } from './clean_client_modules_on_dll_task';
diff --git a/src/dev/build/tasks/nodejs_modules/webpack_dll.js b/src/dev/build/tasks/nodejs_modules/webpack_dll.js
deleted file mode 100644
index 8de5e582c3d36..0000000000000
--- a/src/dev/build/tasks/nodejs_modules/webpack_dll.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { deleteAll, isFileAccessible, read, write } from '../../lib';
-import { dirname, relative, resolve } from 'path';
-import pkgUp from 'pkg-up';
-import globby from 'globby';
-import normalizePosixPath from 'normalize-path';
-
-function checkDllEntryAccess(entry, baseDir = '') {
- const resolvedPath = baseDir ? resolve(baseDir, entry) : entry;
- return isFileAccessible(resolvedPath);
-}
-
-export async function getDllEntries(manifestPaths, whiteListedModules, baseDir = '') {
- // Read and parse all manifests
- const manifests = await Promise.all(
- manifestPaths.map(async (manifestPath) => JSON.parse(await read(manifestPath)))
- );
-
- // Process and group modules from all manifests
- const manifestsModules = manifests.flatMap((manifest, idx) => {
- if (!manifest || !manifest.content) {
- // It should fails because if we don't have the manifest file
- // or it is malformed something wrong is happening and we
- // should stop
- throw new Error(`The following dll manifest doesn't exists: ${manifestPaths[idx]}`);
- }
-
- const modules = Object.keys(manifest.content);
- if (!modules.length) {
- // It should fails because if we don't have any
- // module inside the client vendors dll something
- // wrong is happening and we should stop too
- throw new Error(
- `The following dll manifest is reporting an empty dll: ${manifestPaths[idx]}`
- );
- }
-
- return modules;
- });
-
- // Only includes modules who are not in the white list of modules
- // and that are node_modules
- return manifestsModules.filter((entry) => {
- const isWhiteListed = whiteListedModules.some((nonEntry) =>
- normalizePosixPath(entry).includes(`node_modules/${nonEntry}`)
- );
- const isNodeModule = entry.includes('node_modules');
-
- // NOTE: when using dynamic imports on webpack the entry paths could be created
- // with special context module (ex: lazy recursive) values over directories that are not real files
- // and only exists in runtime, so we need to check if the entry is a real file.
- // We found that problem through the issue https://github.com/elastic/kibana/issues/38481
- //
- // More info:
- // https://github.com/webpack/webpack/blob/master/examples/code-splitting-harmony/README.md
- // https://webpack.js.org/guides/dependency-management/#require-with-expression
- const isAccessible = checkDllEntryAccess(entry, baseDir);
-
- return !isWhiteListed && isNodeModule && isAccessible;
- });
-}
-
-export async function cleanDllModuleFromEntryPath(logger, entryPath) {
- const modulePkgPath = await pkgUp(entryPath);
- const modulePkg = JSON.parse(await read(modulePkgPath));
- const moduleDir = dirname(modulePkgPath);
- const normalizedModuleDir = normalizePosixPath(moduleDir);
-
- // Cancel the cleanup for this module as it
- // was already done.
- if (modulePkg.cleaned) {
- return;
- }
-
- // Clear dependencies from dll module package.json
- if (modulePkg.dependencies) {
- modulePkg.dependencies = {};
- }
-
- // Clear devDependencies from dll module package.json
- if (modulePkg.devDependencies) {
- modulePkg.devDependencies = {};
- }
-
- // Delete module contents. It will delete everything
- // excepts package.json, images and css
- //
- // NOTE: We can't use cwd option with globby
- // until the following issue gets closed
- // https://github.com/sindresorhus/globby/issues/87
- const filesToDelete = await globby([
- `${normalizedModuleDir}/**`,
- `!${normalizedModuleDir}/**/*.+(css)`,
- `!${normalizedModuleDir}/**/*.+(gif|ico|jpeg|jpg|tiff|tif|svg|png|webp)`,
- ]);
-
- await deleteAll(
- filesToDelete.filter((path) => {
- const relativePath = relative(moduleDir, path);
- return !relativePath.endsWith('package.json') || relativePath.includes('node_modules');
- })
- );
-
- // Mark this module as cleaned
- modulePkg.cleaned = true;
-
- // Rewrite modified package.json
- await write(modulePkgPath, JSON.stringify(modulePkg, null, 2));
-}
-
-export async function writeEmptyFileForDllEntry(entryPath) {
- await write(entryPath, '');
-}
diff --git a/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js b/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js
deleted file mode 100644
index ce305169a777b..0000000000000
--- a/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { isFileAccessible, read } from '../../lib';
-import { getDllEntries } from './webpack_dll';
-
-jest.mock('../../lib', () => ({
- read: jest.fn(),
- isFileAccessible: jest.fn(),
-}));
-
-const manifestContentMock = JSON.stringify({
- name: 'vendors',
- content: {
- '/mock/node_modules/dep1': {},
- '/mock/node_modules/dep2': {},
- '/mock/node_modules/dep3': {},
- '/mock/tmp/dep2': {},
- },
-});
-
-const emptyManifestContentMock = JSON.stringify({
- name: 'vendors',
- content: {},
-});
-
-const noManifestMock = JSON.stringify(null);
-
-const noContentFieldManifestMock = JSON.stringify({
- name: 'vendors',
-});
-
-describe('Webpack DLL Build Tasks Utils', () => {
- it('should get dll entries correctly', async () => {
- read.mockImplementationOnce(async () => manifestContentMock);
-
- isFileAccessible.mockImplementation(() => true);
-
- const mockManifestPath = ['/mock/mock_dll_manifest.json'];
- const mockModulesWhitelist = ['dep1'];
- const dllEntries = await getDllEntries(mockManifestPath, mockModulesWhitelist);
-
- expect(dllEntries).toEqual(
- expect.arrayContaining(['/mock/node_modules/dep2', '/mock/node_modules/dep3'])
- );
- });
-
- it('should only include accessible files', async () => {
- read.mockImplementationOnce(async () => manifestContentMock);
-
- isFileAccessible.mockImplementation(() => false);
-
- const mockManifestPath = ['/mock/mock_dll_manifest.json'];
- const mockModulesWhitelist = ['dep1'];
- const dllEntries = await getDllEntries(mockManifestPath, mockModulesWhitelist);
-
- isFileAccessible.mockRestore();
-
- expect(dllEntries.length).toEqual(0);
- });
-
- it('should throw an error for no manifest file', async () => {
- read.mockImplementationOnce(async () => noManifestMock);
-
- const mockManifestPath = ['/mock/mock_dll_manifest.json'];
-
- try {
- await getDllEntries(mockManifestPath, []);
- } catch (error) {
- expect(error.message).toEqual(
- `The following dll manifest doesn't exists: /mock/mock_dll_manifest.json`
- );
- }
- });
-
- it('should throw an error for no manifest content field', async () => {
- read.mockImplementation(async () => noContentFieldManifestMock);
-
- const mockManifestPath = ['/mock/mock_dll_manifest.json'];
-
- try {
- await getDllEntries(mockManifestPath, []);
- } catch (error) {
- expect(error.message).toEqual(
- `The following dll manifest doesn't exists: /mock/mock_dll_manifest.json`
- );
- }
- });
-
- it('should throw an error for manifest file without any content', async () => {
- read.mockImplementation(async () => emptyManifestContentMock);
-
- const mockManifestPath = ['/mock/mock_dll_manifest.json'];
-
- try {
- await getDllEntries(mockManifestPath, []);
- } catch (error) {
- expect(error.message).toEqual(
- `The following dll manifest is reporting an empty dll: /mock/mock_dll_manifest.json`
- );
- }
- });
-
- afterAll(() => {
- jest.clearAllMocks();
- });
-});
diff --git a/src/dev/build/tasks/optimize_task.js b/src/dev/build/tasks/optimize_task.js
index 4034092273239..16a7537b8ac9e 100644
--- a/src/dev/build/tasks/optimize_task.js
+++ b/src/dev/build/tasks/optimize_task.js
@@ -41,7 +41,6 @@ export const OptimizeBuildTask = {
await exec(log, kibanaScript, kibanaArgs, {
cwd: build.resolvePath('.'),
env: {
- FORCE_DLL_CREATION: 'true',
KBN_CACHE_LOADER_WRITABLE: 'true',
NODE_OPTIONS: '--max-old-space-size=4096',
},
diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js b/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js
index 95056d9f0d8d7..ba73922ec508a 100644
--- a/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js
+++ b/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js
@@ -69,96 +69,4 @@ describe('Ingesting coverage', () => {
expect(folderStructure.test(actualUrl)).ok();
});
});
- describe(`vcsInfo`, () => {
- let stdOutWithVcsInfo = '';
- describe(`without a commit msg in the vcs info file`, () => {
- beforeAll(async () => {
- const args = [
- 'scripts/ingest_coverage.js',
- '--verbose',
- '--vcsInfoPath',
- 'src/dev/code_coverage/ingest_coverage/integration_tests/mocks/VCS_INFO_missing_commit_msg.txt',
- '--path',
- ];
- const opts = [...args, resolved];
- const { stdout } = await execa(process.execPath, opts, { cwd: ROOT_DIR, env });
- stdOutWithVcsInfo = stdout;
- });
-
- it(`should be an obj w/o a commit msg`, () => {
- const commitMsgRE = /"commitMsg"/;
- expect(commitMsgRE.test(stdOutWithVcsInfo)).to.not.be.ok();
- });
- });
- describe(`including previous sha`, () => {
- let stdOutWithPrevious = '';
- beforeAll(async () => {
- const opts = [...verboseArgs, resolved];
- const { stdout } = await execa(process.execPath, opts, { cwd: ROOT_DIR, env });
- stdOutWithPrevious = stdout;
- });
-
- it(`should have a vcsCompareUrl`, () => {
- const previousCompareUrlRe = /vcsCompareUrl.+\s*.*https.+compare\/FAKE_PREVIOUS_SHA\.\.\.f07b34f6206/;
- expect(previousCompareUrlRe.test(stdOutWithPrevious)).to.be.ok();
- });
- });
- describe(`with a commit msg in the vcs info file`, () => {
- beforeAll(async () => {
- const args = [
- 'scripts/ingest_coverage.js',
- '--verbose',
- '--vcsInfoPath',
- 'src/dev/code_coverage/ingest_coverage/integration_tests/mocks/VCS_INFO.txt',
- '--path',
- ];
- const opts = [...args, resolved];
- const { stdout } = await execa(process.execPath, opts, { cwd: ROOT_DIR, env });
- stdOutWithVcsInfo = stdout;
- });
-
- it(`should be an obj w/ a commit msg`, () => {
- const commitMsgRE = /commitMsg/;
- expect(commitMsgRE.test(stdOutWithVcsInfo)).to.be.ok();
- });
- });
- });
- describe(`team assignment`, () => {
- let shouldNotHavePipelineOut = '';
- let shouldIndeedHavePipelineOut = '';
-
- const args = [
- 'scripts/ingest_coverage.js',
- '--verbose',
- '--vcsInfoPath',
- 'src/dev/code_coverage/ingest_coverage/integration_tests/mocks/VCS_INFO.txt',
- '--path',
- ];
-
- const teamAssignRE = /pipeline:/;
-
- beforeAll(async () => {
- const summaryPath = 'jest-combined/coverage-summary-just-total.json';
- const resolved = resolve(MOCKS_DIR, summaryPath);
- const opts = [...args, resolved];
- const { stdout } = await execa(process.execPath, opts, { cwd: ROOT_DIR, env });
- shouldNotHavePipelineOut = stdout;
- });
- beforeAll(async () => {
- const summaryPath = 'jest-combined/coverage-summary-manual-mix.json';
- const resolved = resolve(MOCKS_DIR, summaryPath);
- const opts = [...args, resolved];
- const { stdout } = await execa(process.execPath, opts, { cwd: ROOT_DIR, env });
- shouldIndeedHavePipelineOut = stdout;
- });
-
- it(`should not occur when going to the totals index`, () => {
- const actual = teamAssignRE.test(shouldNotHavePipelineOut);
- expect(actual).to.not.be.ok();
- });
- it(`should indeed occur when going to the coverage index`, () => {
- const actual = /ingest-pipe=>team_assignment/.test(shouldIndeedHavePipelineOut);
- expect(actual).to.be.ok();
- });
- });
});
diff --git a/src/dev/notice/generate_notice_from_source.ts b/src/dev/notice/generate_notice_from_source.ts
index fb74bed0f26f4..37bbcce72e497 100644
--- a/src/dev/notice/generate_notice_from_source.ts
+++ b/src/dev/notice/generate_notice_from_source.ts
@@ -47,10 +47,11 @@ export async function generateNoticeFromSource({ productName, directory, log }:
cwd: directory,
nodir: true,
ignore: [
- '{node_modules,build,target,dist,data,built_assets}/**',
- 'packages/*/{node_modules,build,target,dist}/**',
- 'x-pack/{node_modules,build,target,dist,data}/**',
- 'x-pack/packages/*/{node_modules,build,target,dist}/**',
+ '{node_modules,build,dist,data,built_assets}/**',
+ 'packages/*/{node_modules,build,dist}/**',
+ 'x-pack/{node_modules,build,dist,data}/**',
+ 'x-pack/packages/*/{node_modules,build,dist}/**',
+ '**/target/**',
],
};
diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js
index 6b1f1dfaeabb4..929de8c6701d4 100644
--- a/src/dev/precommit_hook/casing_check_config.js
+++ b/src/dev/precommit_hook/casing_check_config.js
@@ -30,6 +30,7 @@ export const IGNORE_FILE_GLOBS = [
'docs/**/*',
'**/bin/**/*',
'**/+([A-Z_]).md',
+ '**/+([A-Z_]).asciidoc',
'**/LICENSE',
'**/*.txt',
'**/Gruntfile.js',
diff --git a/src/es_archiver/lib/indices/create_index_stream.ts b/src/es_archiver/lib/indices/create_index_stream.ts
index 5629f95c7c9c6..fa4c95dc73166 100644
--- a/src/es_archiver/lib/indices/create_index_stream.ts
+++ b/src/es_archiver/lib/indices/create_index_stream.ts
@@ -20,7 +20,6 @@
import { Transform, Readable } from 'stream';
import { inspect } from 'util';
-import { get, once } from 'lodash';
import { Client } from 'elasticsearch';
import { ToolingLog } from '@kbn/dev-utils';
@@ -54,7 +53,7 @@ export function createCreateIndexStream({
// If we're trying to import Kibana index docs, we need to ensure that
// previous indices are removed so we're starting w/ a clean slate for
// migrations. This only needs to be done once per archive load operation.
- const deleteKibanaIndicesOnce = once(deleteKibanaIndices);
+ let kibanaIndexAlreadyDeleted = false;
async function handleDoc(stream: Readable, record: DocRecord) {
if (skipDocsFromIndices.has(record.value.index)) {
@@ -70,8 +69,9 @@ export function createCreateIndexStream({
async function attemptToCreate(attemptNumber = 1) {
try {
- if (isKibana) {
- await deleteKibanaIndicesOnce({ client, stats, log });
+ if (isKibana && !kibanaIndexAlreadyDeleted) {
+ await deleteKibanaIndices({ client, stats, log });
+ kibanaIndexAlreadyDeleted = true;
}
await client.indices.create({
@@ -90,6 +90,7 @@ export function createCreateIndexStream({
err?.body?.error?.reason?.includes('index exists with the same name as the alias') &&
attemptNumber < 3
) {
+ kibanaIndexAlreadyDeleted = false;
const aliasStr = inspect(aliases);
log.info(
`failed to create aliases [${aliasStr}] because ES indicated an index/alias already exists, trying again`
@@ -98,10 +99,7 @@ export function createCreateIndexStream({
return;
}
- if (
- get(err, 'body.error.type') !== 'resource_already_exists_exception' ||
- attemptNumber >= 3
- ) {
+ if (err?.body?.error?.type !== 'resource_already_exists_exception' || attemptNumber >= 3) {
throw err;
}
diff --git a/src/legacy/core_plugins/tests_bundle/index.js b/src/legacy/core_plugins/tests_bundle/index.js
index 431c161585fe0..da7c1c4f4527e 100644
--- a/src/legacy/core_plugins/tests_bundle/index.js
+++ b/src/legacy/core_plugins/tests_bundle/index.js
@@ -108,6 +108,13 @@ export default (kibana) => {
resolve: {
extensions: ['.karma_mock.js', '.karma_mock.tsx', '.karma_mock.ts'],
},
+ node: {
+ fs: 'empty',
+ child_process: 'empty',
+ dns: 'empty',
+ net: 'empty',
+ tls: 'empty',
+ },
},
webpackConfig
);
diff --git a/src/legacy/server/logging/log_format_string.js b/src/legacy/server/logging/log_format_string.js
index 3c18aab2e3d09..cbbf71dd894ac 100644
--- a/src/legacy/server/logging/log_format_string.js
+++ b/src/legacy/server/logging/log_format_string.js
@@ -41,8 +41,6 @@ const typeColors = {
optmzr: 'white',
manager: 'green',
optimize: 'magentaBright',
- 'optimize:dynamic_dll_plugin': 'magentaBright',
- 'optimize:watch_cache': 'magentaBright',
listening: 'magentaBright',
scss: 'magentaBright',
};
diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss
index 323de2ea7d263..a441b773d4a4e 100644
--- a/src/legacy/ui/public/_index.scss
+++ b/src/legacy/ui/public/_index.scss
@@ -1,6 +1,3 @@
-// Legacy styles to come before all
-@import './styles/_legacy/index';
-
// Prefix all styles with "kbn" to avoid conflicts.
// Examples
// kbnChart
diff --git a/src/legacy/ui/public/styles/_legacy/_base.scss b/src/legacy/ui/public/styles/_legacy/_base.scss
deleted file mode 100644
index 877ae033ae584..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/_base.scss
+++ /dev/null
@@ -1,153 +0,0 @@
-@import '@elastic/eui/src/components/collapsible_nav/variables';
-
-// Forms
-
-// Angular form states
-input.ng-invalid,
-textarea.ng-invalid,
-select.ng-invalid {
- &.ng-dirty,
- &.ng-touched {
- border-color: $euiColorDanger !important;
- }
-}
-
-input[type='radio'],
-input[type='checkbox'],
-.radio,
-.radio-inline,
-.checkbox,
-.checkbox-inline {
- &[disabled],
- fieldset[disabled] & {
- cursor: default;
- opacity: 0.8;
- }
-}
-
-.checkbox label {
- display: flex;
- align-items: center;
- padding-left: 0 !important;
-
- input[type='checkbox'] {
- float: none;
- margin: 0 $euiSizeXS;
- position: static;
- }
-}
-
-// Application Layout
-
-// chrome-context
-// TODO #64541
-// Delete this block
-.chrHeaderWrapper:not(.headerWrapper) .content {
- display: flex;
- flex-flow: row nowrap;
- width: 100%;
- height: 100%;
- overflow: hidden;
-}
-
-.application,
-.app-container {
- > * {
- position: relative;
- }
-
- > config {
- z-index: 1;
- }
-
- > navbar {
- padding-bottom: $euiSizeS;
- }
-
- > nav,
- > navbar {
- z-index: 2 !important;
- }
-}
-
-.application {
- position: relative;
- z-index: 0;
- display: flex;
- flex-grow: 1;
- flex-shrink: 0;
- flex-basis: auto;
- flex-direction: column;
-
- > * {
- flex-shrink: 0;
- }
-}
-
-[fixed-scroll] {
- overflow-x: auto;
- padding-bottom: 0;
-
- + .fixed-scroll-scroller {
- position: fixed;
- bottom: 0;
- overflow-x: auto;
- overflow-y: hidden;
- }
-}
-
-// Too overused in many places to be moved elsewhere
-
-.page-row {
- padding: 0 $euiSize;
- margin: $euiSize 0;
-}
-
-.page-row-text {
- color: $euiColorDarkShade;
- font-size: $euiFontSizeS;
-}
-
-// We apply brute force focus states to anything not coming from Eui
-// which has focus states designed at the component level.
-// You can also use "kbn-resetFocusState" to not apply the default focus
-// state. This is useful when you've already hand crafted your own
-// focus states in Kibana.
-:focus {
- &:not([class^='eui']):not(.kbn-resetFocusState) {
- @include euiFocusRing;
- }
-}
-
-// A necessary hack so that the above focus policy doesn't pollute some EUI
-// entrenched inputs.
-.euiComboBox {
- // :not() specificity needed to override the above
- input:not([class^='eui']):focus {
- animation: none !important;
- }
-}
-
-.euiBody--collapsibleNavIsDocked .euiBottomBar {
- margin-left: $euiCollapsibleNavWidth;
-}
-
-// Utility classes
-
-.fullWidth {
- width: 100% !important;
-}
-
-.small {
- font-size: 0.9em !important;
-}
-.smaller {
- font-size: 0.8em !important;
-}
-.smallest {
- font-size: 0.7em !important;
-}
-
-.text-monospace {
- font-family: $euiCodeFontFamily;
-}
diff --git a/src/legacy/ui/public/styles/_legacy/_index.scss b/src/legacy/ui/public/styles/_legacy/_index.scss
deleted file mode 100644
index a0b1a98b09b7d..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/_index.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-// //
-// // KIBANA THEME
-@import './base';
-@import './mixins';
-
-// // Components
-@import './components/index';
diff --git a/src/legacy/ui/public/styles/_legacy/components/_config.scss b/src/legacy/ui/public/styles/_legacy/components/_config.scss
deleted file mode 100644
index b56826f1e7088..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_config.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-// SASSTODO: Selector is so generic it's hard to find if it's actually used
-.config {
- @extend .navbar !optional;
- @extend .navbar-default !optional;
- border-bottom: 1px solid transparent;
-
- .container-fluid {
- background-color: $euiPageBackgroundColor;
- padding: $euiSizeS;
- }
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_control_group.scss b/src/legacy/ui/public/styles/_legacy/components/_control_group.scss
deleted file mode 100644
index ce958a9aae77f..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_control_group.scss
+++ /dev/null
@@ -1,67 +0,0 @@
-.control-group {
- display: flex;
- flex: 0 0 auto;
- flex-direction: row;
- flex-wrap: wrap;
- align-items: stretch;
- padding: $euiSizeXS $euiSize;
-
- > * {
- padding-right: $euiSize;
- flex: 0 0 auto;
-
- &:last-child {
- padding-right: 0;
- }
- }
-
- // horizontal group of buttons/form elements
- .inline-form .input-group {
- margin-bottom: 0;
- display: flex;
-
- > * {
- border-radius: 0;
- }
-
- > :first-child {
- border-bottom-left-radius: $euiBorderRadius;
- border-top-left-radius: $euiBorderRadius;
- }
-
- > :last-child {
- border-bottom-right-radius: $euiBorderRadius;
- border-top-right-radius: $euiBorderRadius;
- }
- }
-
- .inline-form {
- @include flex-parent(0, 0, auto);
- display: flex;
-
- > .typeahead {
- @include flex-parent();
-
- > .input-group {
- display: flex;
- flex: 1 0 auto;
-
- > * {
- float: none;
- height: auto;
- width: auto;
- flex: 0 0 auto;
- }
-
- input[type="text"] {
- flex: 1 1 100%;
- }
- }
- }
- }
-
- // the element should take up an even share of available space
- > .fill {
- flex: 1 1 1%;
- }
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_hintbox.scss b/src/legacy/ui/public/styles/_legacy/components/_hintbox.scss
deleted file mode 100644
index 0c447031636ac..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_hintbox.scss
+++ /dev/null
@@ -1,59 +0,0 @@
-.hintbox {
- padding: $euiSizeS $euiSizeM;
- border-radius: $euiBorderRadius;
- margin-bottom: $euiSizeS;
- background-color: $euiColorLightShade;
- line-height: $euiLineHeight;
-
- a {
- color: $euiLinkColor !important;
-
- &:hover {
- color: darken($euiLinkColor, 10%) !important;
- }
- }
-
- pre {
- background-color: $euiColorEmptyShade;
- }
-
- ul, ol {
- padding-left: $euiSizeL;
- }
-
- // inspired by Bootstrap alerts component
- // https://github.com/twbs/bootstrap/blob/063c1b0780ea0240e4adce4c88d57fc23e099475/less/alerts.less#L27-L35
- > * {
- margin: 0;
- }
-
- > * + * {
- margin-top: $euiSizeS;
- }
-
- // https://github.com/twbs/bootstrap/blob/2aa102bfd40859d15790febed1939e0111a6fb1a/less/tables.less#L88-L106
- .table-bordered {
- border: $euiBorderThin;
- > thead,
- > tbody,
- > tfoot {
- > tr {
- > th,
- > td {
- border: $euiBorderThin;
- }
- }
- }
- > thead > tr {
- > th,
- > td {
- border-bottom-width: 2px;
- }
- }
- }
-}
-
- .hintbox-label,
- .hintbox-label[ng-click] {
- cursor: help;
- }
diff --git a/src/legacy/ui/public/styles/_legacy/components/_index.scss b/src/legacy/ui/public/styles/_legacy/components/_index.scss
deleted file mode 100644
index cfae0700bb71e..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_index.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-@import './ace_overrides';
-@import './control_group';
-@import './hintbox';
-@import './input';
-@import './kui_forms';
-@import './list_group_menu';
-@import './navbar';
-@import './config';
-@import './pagination';
-@import './spinner';
-@import './table';
-@import './truncate';
-@import './ui_select';
diff --git a/src/legacy/ui/public/styles/_legacy/components/_input.scss b/src/legacy/ui/public/styles/_legacy/components/_input.scss
deleted file mode 100644
index 13efc9646e820..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_input.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-i.input-error {
- position: absolute;
- margin-left: -$euiSizeL;
- color: $euiColorDanger;
- margin-top: $euiSizeS;
- z-index: 5;
-}
-
-select {
- color: $euiTextColor;
- background-color: $euiColorEmptyShade;
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_kui_forms.scss b/src/legacy/ui/public/styles/_legacy/components/_kui_forms.scss
deleted file mode 100644
index 2e1b814d647e3..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_kui_forms.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-.form-control {
- @include __legacyInputStyles__bad;
-}
-
-select.form-control {
- @include __legacySelectStyles__bad;
-}
-
-.kuiFormSection {
- margin-bottom: $euiSize;
-}
-
-.kuiFormLabel {
- @include __legacyLabelStyles__bad;
- display: block;
- margin-bottom: 5px;
-}
-
-.kuiInputNote {
- margin: $euiSizeXS 0 $euiSizeS;
-}
-
-.kuiInputNote--danger {
- color: $euiColorDanger;
-}
-
-.kuiInputNote--warning {
- color: $euiColorWarning;
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_navbar.scss b/src/legacy/ui/public/styles/_legacy/components/_navbar.scss
deleted file mode 100644
index b06c655789a50..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_navbar.scss
+++ /dev/null
@@ -1,86 +0,0 @@
-navbar {
- @extend .control-group;
-
- max-height: 340px;
- margin-bottom: 0;
- padding: 0 $euiSizeS $euiSizeXS;
- color: $euiColorDarkShade;
- background-color: $euiColorLightShade;
- border: none;
- z-index: $euiZLevel1;
-
- > * {
- padding-right: $euiSizeS;
- }
-
- .navbar-text {
- margin-top: $euiSizeXS;
- margin-bottom: $euiSizeXS;
- }
-
- // the "brand" that is displayed, usually on the left of the navbar
- > .name {
- @include euiTextTruncate;
-
- align-self: center;
- font-size: $euiFontSizeL;
- }
-
- button {
- color: $euiColorDarkShade;
- background-color: transparent;
-
- &:hover,
- &:focus {
- color: $euiColorDarkShade;
- background-color: transparent;
- }
-
- &:active, &.active {
- color: $euiColorDarkestShade;
- background-color: transparent;
- box-shadow: none;
-
- &:focus {
- outline: none;
- }
- }
-
- &[disabled] {
- color: $euiColorMediumShade;
- background-color: transparent;
- }
- }
-
- .inline-form .input-group {
- button {
- color: $euiColorEmptyShade;
- background-color: $euiColorDarkShade;
- border: none;
- }
- }
-
- // responsive modifications
-
- // desktop
- @include euiBreakpoint('l', 'xl') {
- > .name {
- // 500px is sort of arbitrary, not sure how to deal with lots of buttons
- max-width: 500px;
- }
- }
-
- // tablets/phones
- @include euiBreakpoint('xs', 's', 'm') {
- > .fill {
- flex: 1 1 map-get($euiBreakpoints, 'l');
- }
- }
-
- // phones
- @include euiBreakpoint('xs', 's') {
- > .name {
- max-width: 100%;
- }
- }
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_pagination.scss b/src/legacy/ui/public/styles/_legacy/components/_pagination.scss
deleted file mode 100644
index cf68f2ac8253f..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_pagination.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-paginate {
- display: block;
-
- paginate-controls {
- display: flex;
- align-items: center;
- padding: $euiSizeXS $euiSizeXS $euiSizeS;
- text-align: center;
-
- .pagination-other-pages {
- flex: 1 0 auto;
- display: flex;
- justify-content: center;
- }
-
- .pagination-other-pages-list {
- flex: 0 0 auto;
- display: flex;
- justify-content: center;
- padding: 0;
- margin: 0;
- list-style: none;
-
- > li {
- flex: 0 0 auto;
- user-select: none;
-
- a {
- text-decoration: none;
- background-color: $euiColorLightestShade;
- margin-left: $euiSizeXS / 2;
- padding: $euiSizeS $euiSizeM;
- }
-
- a:hover {
- text-decoration: underline;
- }
-
- &.active a {
- text-decoration: none !important;
- font-weight: $euiFontWeightBold;
- color: $euiColorDarkShade;
- cursor: default;
- }
- }
- }
-
- .pagination-size {
- flex: 0 0 auto;
-
- input[type=number] {
- width: 3em;
- }
- }
- }
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_spinner.scss b/src/legacy/ui/public/styles/_legacy/components/_spinner.scss
deleted file mode 100644
index 7b3b1bd615ae0..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_spinner.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-.spinner.ng-hide {
- visibility: hidden;
- display: block !important;
- opacity: 0;
- transition-delay: 0.25s;
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_table.scss b/src/legacy/ui/public/styles/_legacy/components/_table.scss
deleted file mode 100644
index d0ac9d6f79862..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_table.scss
+++ /dev/null
@@ -1,46 +0,0 @@
-@import '../../../../../../plugins/discover/public/application/mixins';
-
-.table {
- // Nesting
- .table {
- background-color: $euiColorEmptyShade;
- }
-}
-
-kbn-table, .kbn-table, tbody[kbn-rows] {
- @include dscDocSourceStyle;
- // sub tables should not have a leading border
- .table .table {
- margin-bottom: 0;
-
- tr:first-child > td {
- border-top: none;
- }
-
- td.field-name {
- font-weight: $euiFontWeightBold;
- }
- }
-}
-
-table {
- th {
- i.fa-sort {
- color: $euiColorLightShade;
- }
-
- button.fa-sort-asc,
- button.fa-sort-down,
- i.fa-sort-asc,
- i.fa-sort-down {
- color: $euiColorPrimary;
- }
-
- button.fa-sort-desc,
- button.fa-sort-up,
- i.fa-sort-desc,
- i.fa-sort-up {
- color: $euiColorPrimary;
- }
- }
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_truncate.scss b/src/legacy/ui/public/styles/_legacy/components/_truncate.scss
deleted file mode 100644
index 30ba5fea2a4ea..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_truncate.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.truncate-by-height {
- overflow: hidden;
-}
diff --git a/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss b/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss
deleted file mode 100644
index 691ec17b5b967..0000000000000
--- a/src/legacy/ui/public/styles/_legacy/components/_ui_select.scss
+++ /dev/null
@@ -1,357 +0,0 @@
-/*!
- * ui-select
- * http://github.com/angular-ui/ui-select
- * Version: 0.19.5 - 2016-10-24T23:13:59.551Z
- * License: MIT
- */
-
-/* Style when highlighting a search. */
-.ui-select-highlight {
- font-weight: bold;
-}
-
-.ui-select-offscreen {
- clip: rect(0 0 0 0) !important;
- width: 1px !important;
- height: 1px !important;
- border: 0 !important;
- margin: 0 !important;
- padding: 0 !important;
- overflow: hidden !important;
- position: absolute !important;
- outline: 0 !important;
- left: 0px !important;
- top: 0px !important;
-}
-
-.ui-select-choices-row:hover {
- background-color: $euiColorLightestShade;
-}
-
-/* Select2 theme */
-
-/* Mark invalid Select2 */
-.ng-dirty.ng-invalid > a.select2-choice {
- border-color: $euiColorDanger;
-}
-
-.select2-result-single {
- padding-left: 0;
-}
-
-.select2-locked > .select2-search-choice-close {
- display: none;
-}
-
-.select-locked > .ui-select-match-close {
- display: none;
-}
-
-body > .select2-container.open {
- z-index: 9999; /* The z-index Select2 applies to the select2-drop */
-}
-
-/* Handle up direction Select2 */
-.ui-select-container[theme='select2'].direction-up .ui-select-match,
-.ui-select-container.select2.direction-up .ui-select-match {
- border-radius: 4px; /* FIXME hardcoded value :-/ */
- border-top-left-radius: 0;
- border-top-right-radius: 0;
-}
-.ui-select-container[theme='select2'].direction-up .ui-select-dropdown,
-.ui-select-container.select2.direction-up .ui-select-dropdown {
- border-radius: 4px; /* FIXME hardcoded value :-/ */
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
-
- border-top-width: 1px; /* FIXME hardcoded value :-/ */
- border-top-style: solid;
-
- box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
-
- margin-top: -4px; /* FIXME hardcoded value :-/ */
-}
-.ui-select-container[theme='select2'].direction-up .ui-select-dropdown .select2-search,
-.ui-select-container.select2.direction-up .ui-select-dropdown .select2-search {
- margin-top: 4px; /* FIXME hardcoded value :-/ */
-}
-.ui-select-container[theme='select2'].direction-up.select2-dropdown-open .ui-select-match,
-.ui-select-container.select2.direction-up.select2-dropdown-open .ui-select-match {
- border-bottom-color: $euiColorPrimary;
-}
-
-.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden,
-.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden input {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border: 0;
-}
-
-/* Bootstrap theme */
-
-/* Helper class to show styles when focus */
-.btn-default-focus {
- color: $euiTextColor;
- background-color: $euiColorEmptyShade;
- border-color: $euiColorPrimary;
- text-decoration: none;
- outline: none;
- box-shadow: none;
-}
-
-.ui-select-bootstrap .ui-select-toggle {
- @include __legacyInputStyles__bad;
- @include __legacySelectStyles__bad;
-}
-
-.ui-select-bootstrap .ui-select-toggle > .caret {
- display: none;
-}
-
-/* Fix Bootstrap dropdown position when inside a input-group */
-.input-group > .ui-select-bootstrap.dropdown {
- /* Instead of relative */
- position: static;
-}
-
-.input-group > .ui-select-bootstrap > input.ui-select-search.form-control {
- border-radius: 4px; /* FIXME hardcoded value :-/ */
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
-}
-.input-group > .ui-select-bootstrap > input.ui-select-search.form-control.direction-up {
- border-radius: 4px !important; /* FIXME hardcoded value :-/ */
- border-top-right-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
-}
-
-.ui-select-bootstrap .ui-select-search-hidden {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border: 0;
-}
-
-.ui-select-bootstrap > .ui-select-match > .btn {
- @include __legacyInputStyles__bad;
- @include __legacySelectStyles__bad;
- text-align: left !important; // Instead of center because of .btn
-
- .ui-select-placeholder {
- color: $euiColorMediumShade;
- }
-
- &:focus,
- &:active {
- background-color: $euiColorEmptyShade;
- color: $euiTextColor;
- outline: none;
- }
-}
-
-.ui-select-bootstrap > .ui-select-match > .caret {
- display: none;
-}
-
-/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */
-.ui-select-bootstrap > .ui-select-choices,
-.ui-select-bootstrap > .ui-select-no-choice {
- width: 100%;
- height: auto;
- max-height: $euiSize * 14;
- overflow-x: hidden;
-}
-
-body > .ui-select-bootstrap.open {
- z-index: $euiZContentMenu;
-}
-
-.ui-select-multiple.ui-select-bootstrap {
- height: auto;
- padding: 3px 5px 2px;
- border: $euiBorderThin;
- background-color: $euiFormBackgroundColor;
-
- &.kuiInputError {
- border-color: $euiColorDanger;
- }
-}
-
-.ui-select-multiple.ui-select-bootstrap input.ui-select-search {
- background-color: transparent !important; /* To prevent double background when disabled */
- border: none;
- outline: none;
- height: 1.666666em;
- margin-bottom: 3px;
-}
-
-.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
- font-size: 1.6em;
- line-height: 0.75;
-}
-
-.ui-select-multiple.ui-select-bootstrap .ui-select-match-item {
- outline: 0;
- margin: 0 3px 3px 0;
-}
-
-.ui-select-multiple .ui-select-match-item {
- position: relative;
-}
-
-.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close {
- pointer-events: none;
-}
-
-.ui-select-multiple:hover .ui-select-match-item.dropping-before:before {
- content: '';
- position: absolute;
- top: 0;
- right: 100%;
- height: 100%;
- margin-right: 2px;
- border-left: 1px solid $euiColorPrimary;
-}
-
-.ui-select-multiple:hover .ui-select-match-item.dropping-after:after {
- content: '';
- position: absolute;
- top: 0;
- left: 100%;
- height: 100%;
- margin-left: 2px;
- border-right: 1px solid $euiColorPrimary;
-}
-
-.ui-select-bootstrap .ui-select-choices-row > span {
- @include euiFontSizeS;
- @include euiTextTruncate;
- font-weight: inherit;
- cursor: pointer;
- display: block;
- padding: $euiSizeXS $euiSize;
- clear: both;
- color: $euiTextColor;
- white-space: nowrap;
-
- &:hover,
- &:focus {
- text-decoration: none;
- color: $euiTextColor;
- background-color: $euiFocusBackgroundColor;
- }
-}
-
-.ui-select-bootstrap .ui-select-choices-row.active > span {
- color: $euiTextColor;
- text-decoration: none;
- outline: 0;
- background-color: $euiFocusBackgroundColor;
-}
-
-.ui-select-bootstrap .ui-select-choices-row.disabled > span,
-.ui-select-bootstrap .ui-select-choices-row.active.disabled > span {
- color: $euiButtonColorDisabled;
- cursor: not-allowed;
- background-color: transparent;
-}
-
-/* fix hide/show angular animation */
-.ui-select-match.ng-hide-add,
-.ui-select-search.ng-hide-add {
- display: none !important;
-}
-
-/* Mark invalid Bootstrap */
-.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
- border-color: $euiColorDanger;
-}
-
-/* Handle up direction Bootstrap */
-.ui-select-container[theme='bootstrap'].direction-up .ui-select-dropdown {
- @include euiBottomShadowMedium;
-}
-
-.ui-select-bootstrap .ui-select-match-text {
- width: 100%;
- padding-right: 1em;
-}
-.ui-select-bootstrap .ui-select-match-text span {
- display: inline-block;
- width: 100%;
- overflow: hidden;
-}
-.ui-select-bootstrap .ui-select-toggle > a.btn {
- position: absolute;
- height: 10px;
- right: 10px;
- margin-top: -2px;
-}
-
-/* Spinner */
-.ui-select-refreshing {
- position: absolute;
- right: 0;
- padding: 8px 27px;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
-}
-
-@-webkit-keyframes ui-select-spin {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- 100% {
- -webkit-transform: rotate(359deg);
- transform: rotate(359deg);
- }
-}
-@keyframes ui-select-spin {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- 100% {
- -webkit-transform: rotate(359deg);
- transform: rotate(359deg);
- }
-}
-
-.ui-select-spin {
- -webkit-animation: ui-select-spin 2s infinite linear;
- animation: ui-select-spin 2s infinite linear;
-}
-
-.ui-select-refreshing.ng-animate {
- -webkit-animation: none 0s;
-}
-
-// Other Custom
-
-/**
- * 1. Fix appearance of ui-select in the Filtering UI.
- */
-.btn-default .ui-select-placeholder {
- color: $euiColorMediumShade; /* 1 */
-}
-
-.uiSelectMatch--ellipsis {
- @include euiTextTruncate;
-}
-
-.ui-select-choices-group-label {
- @include euiTitle('xxxs');
- @include euiTextTruncate;
- padding: $euiSizeXS;
-}
diff --git a/src/legacy/ui/public/styles/_mixins.scss b/src/legacy/ui/public/styles/_mixins.scss
index c0dc456000dcc..e335ef88a01b5 100644
--- a/src/legacy/ui/public/styles/_mixins.scss
+++ b/src/legacy/ui/public/styles/_mixins.scss
@@ -105,12 +105,10 @@
@keyframes kibanaFullScreenGraphics_FadeIn {
from {
opacity: 0;
- transform: translateY(200px), scale(.75);
}
to {
opacity: 1;
- transform: translateY(0), scale(1);
}
}
}
diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js
index 168dddf0253d9..7788aeaee72e5 100644
--- a/src/legacy/ui/ui_render/ui_render_mixin.js
+++ b/src/legacy/ui/ui_render/ui_render_mixin.js
@@ -24,7 +24,6 @@ import { i18n } from '@kbn/i18n';
import * as UiSharedDeps from '@kbn/ui-shared-deps';
import { AppBootstrap } from './bootstrap';
import { getApmConfig } from '../apm';
-import { DllCompiler } from '../../../optimize/dynamic_dll_plugin';
/**
* @typedef {import('../../server/kbn_server').default} KbnServer
@@ -106,17 +105,8 @@ export function uiRenderMixin(kbnServer, server, config) {
const basePath = config.get('server.basePath');
const regularBundlePath = `${basePath}/${buildHash}/bundles`;
- const dllBundlePath = `${basePath}/${buildHash}/built_assets/dlls`;
-
- const dllStyleChunks = DllCompiler.getRawDllConfig().chunks.map(
- (chunk) => `${dllBundlePath}/vendors${chunk}.style.dll.css`
- );
- const dllJsChunks = DllCompiler.getRawDllConfig().chunks.map(
- (chunk) => `${dllBundlePath}/vendors${chunk}.bundle.dll.js`
- );
const styleSheetPaths = [
- ...(isCore ? [] : dllStyleChunks),
`${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.baseCssDistFilename}`,
...(darkMode
? [
@@ -173,7 +163,6 @@ export function uiRenderMixin(kbnServer, server, config) {
(filename) => `${regularBundlePath}/kbn-ui-shared-deps/${filename}`
),
`${regularBundlePath}/kbn-ui-shared-deps/${UiSharedDeps.jsFilename}`,
- ...(isCore ? [] : [`${dllBundlePath}/vendors_runtime.bundle.dll.js`, ...dllJsChunks]),
`${regularBundlePath}/core/core.entry.js`,
...kpPluginBundlePaths,
diff --git a/src/optimize/base_optimizer.js b/src/optimize/base_optimizer.js
index 55752db55e28a..41628a2264193 100644
--- a/src/optimize/base_optimizer.js
+++ b/src/optimize/base_optimizer.js
@@ -30,8 +30,6 @@ import webpackMerge from 'webpack-merge';
import WrapperPlugin from 'wrapper-webpack-plugin';
import * as UiSharedDeps from '@kbn/ui-shared-deps';
-import { DynamicDllPlugin } from './dynamic_dll_plugin';
-
import { IS_KIBANA_DISTRIBUTABLE } from '../legacy/utils';
import { fromRoot } from '../core/server/utils';
import { PUBLIC_PATH_PLACEHOLDER } from './public_path_placeholder';
@@ -286,12 +284,6 @@ export default class BaseOptimizer {
},
plugins: [
- new DynamicDllPlugin({
- uiBundles: this.uiBundles,
- threadLoaderPoolConfig: this.getThreadLoaderPoolConfig(),
- logWithMetadata: this.logWithMetadata,
- }),
-
new MiniCssExtractPlugin({
filename: '[name].style.css',
}),
diff --git a/src/optimize/bundles_route/__tests__/bundles_route.js b/src/optimize/bundles_route/__tests__/bundles_route.js
index 902fa59b20569..5b42b658300fe 100644
--- a/src/optimize/bundles_route/__tests__/bundles_route.js
+++ b/src/optimize/bundles_route/__tests__/bundles_route.js
@@ -56,7 +56,6 @@ describe('optimizer/bundle route', () => {
function createServer(options = {}) {
const {
regularBundlesPath = outputFixture,
- dllBundlesPath = outputFixture,
basePublicPath = '',
builtCssPath = outputFixture,
npUiPluginPublicDirs = [],
@@ -70,7 +69,6 @@ describe('optimizer/bundle route', () => {
server.route(
createBundlesRoute({
regularBundlesPath,
- dllBundlesPath,
basePublicPath,
builtCssPath,
npUiPluginPublicDirs,
@@ -89,28 +87,24 @@ describe('optimizer/bundle route', () => {
expect(() => {
createBundlesRoute({
regularBundlesPath: null,
- dllBundlesPath: '/absolute/path',
basePublicPath: '',
});
}).to.throwError(/absolute path/);
expect(() => {
createBundlesRoute({
regularBundlesPath: './relative',
- dllBundlesPath: '/absolute/path',
basePublicPath: '',
});
}).to.throwError(/absolute path/);
expect(() => {
createBundlesRoute({
regularBundlesPath: 1234,
- dllBundlesPath: '/absolute/path',
basePublicPath: '',
});
}).to.throwError(/absolute path/);
expect(() => {
createBundlesRoute({
regularBundlesPath: '/absolute/path',
- dllBundlesPath: '/absolute/path',
basePublicPath: '',
});
}).to.not.throwError();
@@ -119,42 +113,36 @@ describe('optimizer/bundle route', () => {
expect(() => {
createBundlesRoute({
regularBundlesPath: '/bundles',
- dllBundlesPath: '/absolute/path',
basePublicPath: 123,
});
}).to.throwError(/string/);
expect(() => {
createBundlesRoute({
regularBundlesPath: '/bundles',
- dllBundlesPath: '/absolute/path',
basePublicPath: {},
});
}).to.throwError(/string/);
expect(() => {
createBundlesRoute({
regularBundlesPath: '/bundles',
- dllBundlesPath: '/absolute/path',
basePublicPath: '/a/',
});
}).to.throwError(/start and not end with a \//);
expect(() => {
createBundlesRoute({
regularBundlesPath: '/bundles',
- dllBundlesPath: '/absolute/path',
basePublicPath: 'a/',
});
}).to.throwError(/start and not end with a \//);
expect(() => {
createBundlesRoute({
regularBundlesPath: '/bundles',
- dllBundlesPath: '/absolute/path',
basePublicPath: '/a',
});
}).to.not.throwError();
expect(() => {
createBundlesRoute({
regularBundlesPath: '/bundles',
- dllBundlesPath: '/absolute/path',
basePublicPath: '',
});
}).to.not.throwError();
diff --git a/src/optimize/bundles_route/bundles_route.ts b/src/optimize/bundles_route/bundles_route.ts
index e9cfba0130d95..8c1092efed252 100644
--- a/src/optimize/bundles_route/bundles_route.ts
+++ b/src/optimize/bundles_route/bundles_route.ts
@@ -28,22 +28,19 @@ import { assertIsNpUiPluginPublicDirs, NpUiPluginPublicDirs } from '../np_ui_plu
import { fromRoot } from '../../core/server/utils';
/**
- * Creates the routes that serves files from `bundlesPath` or from
- * `dllBundlesPath` (if they are dll bundle's related files). If the
+ * Creates the routes that serves files from `bundlesPath`. If the
* file is js or css then it is searched for instances of
* PUBLIC_PATH_PLACEHOLDER and replaces them with `publicPath`.
*
* @param {Object} options
* @property {Array<{id,path}>} options.npUiPluginPublicDirs array of ids and paths that should be served for new platform plugins
* @property {string} options.regularBundlesPath
- * @property {string} options.dllBundlesPath
* @property {string} options.basePublicPath
*
* @return Array.of({Hapi.Route})
*/
export function createBundlesRoute({
regularBundlesPath,
- dllBundlesPath,
basePublicPath,
builtCssPath,
npUiPluginPublicDirs = [],
@@ -51,7 +48,6 @@ export function createBundlesRoute({
isDist = false,
}: {
regularBundlesPath: string;
- dllBundlesPath: string;
basePublicPath: string;
builtCssPath: string;
npUiPluginPublicDirs?: NpUiPluginPublicDirs;
@@ -70,12 +66,6 @@ export function createBundlesRoute({
);
}
- if (typeof dllBundlesPath !== 'string' || !isAbsolute(dllBundlesPath)) {
- throw new TypeError(
- 'dllBundlesPath must be an absolute path to the directory containing the dll bundles'
- );
- }
-
if (typeof basePublicPath !== 'string') {
throw new TypeError('basePublicPath must be a string');
}
@@ -118,13 +108,6 @@ export function createBundlesRoute({
fileHashCache,
isDist,
}),
- buildRouteForBundles({
- publicPath: `${basePublicPath}/${buildHash}/built_assets/dlls/`,
- routePath: `/${buildHash}/built_assets/dlls/`,
- bundlesPath: dllBundlesPath,
- fileHashCache,
- isDist,
- }),
buildRouteForBundles({
publicPath: `${basePublicPath}/`,
routePath: `/${buildHash}/built_assets/css/`,
diff --git a/src/optimize/bundles_route/proxy_bundles_route.ts b/src/optimize/bundles_route/proxy_bundles_route.ts
index 1d189054324a1..108d253d45202 100644
--- a/src/optimize/bundles_route/proxy_bundles_route.ts
+++ b/src/optimize/bundles_route/proxy_bundles_route.ts
@@ -28,7 +28,6 @@ export function createProxyBundlesRoute({
}) {
return [
buildProxyRouteForBundles(`/${buildHash}/bundles/`, host, port),
- buildProxyRouteForBundles(`/${buildHash}/built_assets/dlls/`, host, port),
buildProxyRouteForBundles(`/${buildHash}/built_assets/css/`, host, port),
];
}
diff --git a/src/optimize/dynamic_dll_plugin/dll_allowed_modules.js b/src/optimize/dynamic_dll_plugin/dll_allowed_modules.js
deleted file mode 100644
index 4314cebd3b7e9..0000000000000
--- a/src/optimize/dynamic_dll_plugin/dll_allowed_modules.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import path from 'path';
-
-export function notInNodeModules(checkPath) {
- return !checkPath.includes(`${path.sep}node_modules${path.sep}`);
-}
-
-export function notInNodeModulesOrWebpackShims(checkPath) {
- return notInNodeModules(checkPath) && !checkPath.includes(`${path.sep}webpackShims${path.sep}`);
-}
-
-export function inPluginNodeModules(checkPath) {
- return checkPath.match(/[\/\\]plugins.*[\/\\]node_modules/);
-}
-
-export function inDllPluginPublic(checkPath) {
- return checkPath.includes(`${path.sep}dynamic_dll_plugin${path.sep}public${path.sep}`);
-}
diff --git a/src/optimize/dynamic_dll_plugin/dll_compiler.js b/src/optimize/dynamic_dll_plugin/dll_compiler.js
deleted file mode 100644
index 9ab21ee0e9076..0000000000000
--- a/src/optimize/dynamic_dll_plugin/dll_compiler.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { configModel } from './dll_config_model';
-import {
- notInNodeModulesOrWebpackShims,
- notInNodeModules,
- inDllPluginPublic,
-} from './dll_allowed_modules';
-import {
- dllEntryFileContentArrayToString,
- dllEntryFileContentStringToArray,
- dllMergeAllEntryFilesContent,
-} from './dll_entry_template';
-import { fromRoot } from '../../core/server/utils';
-import { PUBLIC_PATH_PLACEHOLDER } from '../public_path_placeholder';
-import fs from 'fs';
-import webpack from 'webpack';
-import { promisify } from 'util';
-import path from 'path';
-import del from 'del';
-import { chunk } from 'lodash';
-import seedrandom from 'seedrandom';
-
-const readFileAsync = promisify(fs.readFile);
-const mkdirAsync = promisify(fs.mkdir);
-const accessAsync = promisify(fs.access);
-const writeFileAsync = promisify(fs.writeFile);
-
-export class DllCompiler {
- static getRawDllConfig(
- uiBundles = {},
- babelLoaderCacheDir = '',
- threadLoaderPoolConfig = {},
- chunks = Array.from(Array(4).keys()).map((chunkN) => `_${chunkN}`)
- ) {
- return {
- uiBundles,
- babelLoaderCacheDir,
- threadLoaderPoolConfig,
- chunks,
- context: fromRoot('.'),
- entryName: 'vendors',
- dllName: '[name]',
- manifestName: '[name]',
- styleName: '[name]',
- entryExt: '.entry.dll.js',
- dllExt: '.bundle.dll.js',
- manifestExt: '.manifest.dll.json',
- styleExt: '.style.dll.css',
- outputPath: fromRoot('built_assets/dlls'),
- publicPath: PUBLIC_PATH_PLACEHOLDER,
- };
- }
-
- constructor(uiBundles, threadLoaderPoolConfig, logWithMetadata) {
- this.rawDllConfig = DllCompiler.getRawDllConfig(
- uiBundles,
- uiBundles.getCacheDirectory('babel'),
- threadLoaderPoolConfig
- );
- this.logWithMetadata = logWithMetadata || (() => null);
- }
-
- async init() {
- await this.ensureEntryFilesExists();
- await this.ensureManifestFilesExists();
- await this.ensureOutputPathExists();
- }
-
- seededShuffle(array) {
- // Implementation based on https://github.com/TimothyGu/knuth-shuffle-seeded/blob/gh-pages/index.js#L46
- let currentIndex;
- let temporaryValue;
- let randomIndex;
- const rand = seedrandom('predictable', { global: false });
-
- if (array.constructor !== Array) throw new Error('Input is not an array');
- currentIndex = array.length;
-
- // While there remain elements to shuffle...
- while (0 !== currentIndex) {
- // Pick a remaining element...
- randomIndex = Math.floor(rand() * currentIndex--);
-
- // And swap it with the current element.
- temporaryValue = array[currentIndex];
- array[currentIndex] = array[randomIndex];
- array[randomIndex] = temporaryValue;
- }
-
- return array;
- }
-
- async upsertEntryFiles(content) {
- const arrayContent = this.seededShuffle(dllEntryFileContentStringToArray(content));
- const chunks = chunk(
- arrayContent,
- Math.ceil(arrayContent.length / this.rawDllConfig.chunks.length)
- );
- const entryPaths = this.getEntryPaths();
-
- await Promise.all(
- entryPaths.map(
- async (entryPath, idx) =>
- await this.upsertFile(entryPath, dllEntryFileContentArrayToString(chunks[idx]))
- )
- );
- }
-
- async upsertFile(filePath, content = '') {
- await this.ensurePathExists(filePath);
- await writeFileAsync(filePath, content, 'utf8');
- }
-
- getDllPaths() {
- return this.rawDllConfig.chunks.map((chunk) =>
- this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.dllExt}`)
- );
- }
-
- getEntryPaths() {
- return this.rawDllConfig.chunks.map((chunk) =>
- this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.entryExt}`)
- );
- }
-
- getManifestPaths() {
- return this.rawDllConfig.chunks.map((chunk) =>
- this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.manifestExt}`)
- );
- }
-
- getStylePaths() {
- return this.rawDllConfig.chunks.map((chunk) =>
- this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.styleExt}`)
- );
- }
-
- async ensureEntryFilesExists() {
- const entryPaths = this.getEntryPaths();
-
- await Promise.all(entryPaths.map(async (entryPath) => await this.ensureFileExists(entryPath)));
- }
-
- async ensureManifestFilesExists() {
- const manifestPaths = this.getManifestPaths();
-
- await Promise.all(
- manifestPaths.map(
- async (manifestPath, idx) =>
- await this.ensureFileExists(
- manifestPath,
- JSON.stringify({
- name: `${this.rawDllConfig.entryName}${this.rawDllConfig.chunks[idx]}`,
- content: {},
- })
- )
- )
- );
- }
-
- async ensureStyleFileExists() {
- const stylePaths = this.getStylePaths();
-
- await Promise.all(stylePaths.map(async (stylePath) => await this.ensureFileExists(stylePath)));
- }
-
- async ensureFileExists(filePath, content) {
- const exists = await this.ensurePathExists(filePath);
-
- if (!exists) {
- await this.upsertFile(filePath, content);
- }
- }
-
- async ensurePathExists(filePath) {
- try {
- await accessAsync(filePath);
- } catch (e) {
- await mkdirAsync(path.dirname(filePath), { recursive: true });
- return false;
- }
-
- return true;
- }
-
- async ensureOutputPathExists() {
- await this.ensurePathExists(this.rawDllConfig.outputPath);
- }
-
- dllsExistsSync() {
- const dllPaths = this.getDllPaths();
-
- return dllPaths.every((dllPath) => this.existsSync(dllPath));
- }
-
- existsSync(filePath) {
- return fs.existsSync(filePath);
- }
-
- resolvePath() {
- return path.resolve(this.rawDllConfig.outputPath, ...arguments);
- }
-
- async readEntryFiles() {
- const entryPaths = this.getEntryPaths();
-
- const entryFilesContent = await Promise.all(
- entryPaths.map(async (entryPath) => await this.readFile(entryPath))
- );
-
- // merge all the module contents from entry files again into
- // sorted single one
- return dllMergeAllEntryFilesContent(entryFilesContent);
- }
-
- async readFile(filePath, content) {
- await this.ensureFileExists(filePath, content);
- return await readFileAsync(filePath, 'utf8');
- }
-
- async run(dllEntries) {
- const dllConfig = this.dllConfigGenerator(this.rawDllConfig);
- await this.upsertEntryFiles(dllEntries);
-
- try {
- this.logWithMetadata(
- ['info', 'optimize:dynamic_dll_plugin'],
- 'Client vendors dll compilation started'
- );
-
- await this.runWebpack(dllConfig());
-
- this.logWithMetadata(
- ['info', 'optimize:dynamic_dll_plugin'],
- `Client vendors dll compilation finished with success`
- );
- } catch (e) {
- this.logWithMetadata(
- ['fatal', 'optimize:dynamic_dll_plugin'],
- `Client vendors dll compilation failed`
- );
-
- // Still throw the original error has here we just want
- // log the fail message
- throw e;
- }
-
- // Style dll file isn't always created but we are
- // expecting it to exist always as we are referencing
- // it from the bootstrap template
- //
- // NOTE: We should review the way we deal with the css extraction
- // in ours webpack builds. The industry standard is about to
- // only extract css for production but we are extracting it
- // in every single compilation.
- await this.ensureStyleFileExists();
- }
-
- dllConfigGenerator(dllConfig) {
- return configModel.bind(this, dllConfig);
- }
-
- async runWebpack(config) {
- return new Promise((resolve, reject) => {
- webpack(config, async (err, stats) => {
- // If a critical error occurs or we have
- // errors in the stats compilation,
- // reject the promise and logs the errors
- const webpackErrors =
- err ||
- (stats.hasErrors() &&
- stats.toString({
- all: false,
- colors: true,
- errors: true,
- errorDetails: true,
- moduleTrace: true,
- }));
-
- if (webpackErrors) {
- // Reject with webpack fatal errors
- return reject(webpackErrors);
- }
-
- // Identify if we have not allowed modules
- // bundled inside the dll bundle
- const notAllowedModules = [];
-
- stats.compilation.modules.forEach((module) => {
- // ignore if no module or userRequest are defined
- if (!module || !module.resource) {
- return;
- }
-
- // ignore if this module represents the
- // dll entry file
- if (this.getEntryPaths().includes(module.resource)) {
- return;
- }
-
- // ignore if this module is part of the
- // files inside dynamic dll plugin public folder
- if (inDllPluginPublic(module.resource)) {
- return;
- }
-
- // A module is not allowed if it's not a node_module, a webpackShim
- // or the reasons from being bundled into the dll are not node_modules
- if (notInNodeModulesOrWebpackShims(module.resource)) {
- const reasons = module.reasons || [];
-
- reasons.forEach((reason) => {
- // Skip if we can't read the reason info
- if (!reason || !reason.module || !reason.module.resource) {
- return;
- }
-
- // Is the reason for this module being bundle a
- // node_module or no?
- if (notInNodeModules(reason.module.resource)) {
- notAllowedModules.push(module.resource);
- }
- });
- }
- });
-
- if (notAllowedModules.length) {
- // Delete the built dll, as it contains invalid modules, and reject listing
- // all the not allowed modules
- try {
- await del(this.rawDllConfig.outputPath);
- } catch (e) {
- return reject(e);
- }
-
- return reject(
- `The following modules are not allowed to be bundled into the dll: \n${notAllowedModules.join(
- '\n'
- )}`
- );
- }
-
- // Otherwise it has succeed
- return resolve(stats);
- });
- });
- }
-}
diff --git a/src/optimize/dynamic_dll_plugin/dll_config_model.js b/src/optimize/dynamic_dll_plugin/dll_config_model.js
deleted file mode 100644
index eec369b194fef..0000000000000
--- a/src/optimize/dynamic_dll_plugin/dll_config_model.js
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { IS_KIBANA_DISTRIBUTABLE } from '../../legacy/utils';
-import { fromRoot } from '../../core/server/utils';
-import webpack from 'webpack';
-import webpackMerge from 'webpack-merge';
-import MiniCssExtractPlugin from 'mini-css-extract-plugin';
-import TerserPlugin from 'terser-webpack-plugin';
-import * as UiSharedDeps from '@kbn/ui-shared-deps';
-
-function generateDLL(config) {
- const {
- dllAlias,
- dllValidateSyntax,
- dllNoParseRules,
- dllContext,
- dllEntry,
- dllOutputPath,
- dllPublicPath,
- dllBundleName,
- dllBundleFilename,
- dllStyleFilename,
- dllManifestPath,
- babelLoaderCacheDir,
- threadLoaderPoolConfig,
- } = config;
-
- const BABEL_PRESET_PATH = require.resolve('@kbn/babel-preset/webpack_preset');
- const BABEL_EXCLUDE_RE = [/[\/\\](webpackShims|node_modules|bower_components)[\/\\]/];
-
- /**
- * Wrap plugin loading in a function so that we can require
- * `@kbn/optimizer` only when absolutely necessary since we
- * don't ship this package in the distributable but this code
- * is still shipped, though it's not used.
- */
- const getValidateSyntaxPlugins = () => {
- if (!dllValidateSyntax) {
- return [];
- }
-
- // only require @kbn/optimizer
- const { DisallowedSyntaxPlugin } = require('@kbn/optimizer');
- return [new DisallowedSyntaxPlugin()];
- };
-
- return {
- entry: dllEntry,
- context: dllContext,
- output: {
- futureEmitAssets: true, // TODO: remove on webpack 5
- filename: dllBundleFilename,
- path: dllOutputPath,
- publicPath: dllPublicPath,
- library: dllBundleName,
- },
- node: { fs: 'empty', child_process: 'empty', dns: 'empty', net: 'empty', tls: 'empty' },
- resolve: {
- extensions: ['.js', '.json'],
- mainFields: ['browser', 'browserify', 'main'],
- alias: dllAlias,
- modules: ['webpackShims', fromRoot('webpackShims'), 'node_modules', fromRoot('node_modules')],
- },
- module: {
- rules: [
- {
- resource: [
- {
- test: /\.js$/,
- exclude: BABEL_EXCLUDE_RE.concat(dllNoParseRules),
- },
- {
- test: /\.js$/,
- include: /[\/\\]node_modules[\/\\]x-pack[\/\\]/,
- exclude: /[\/\\]node_modules[\/\\]x-pack[\/\\](.+?[\/\\])*node_modules[\/\\]/,
- },
- // TODO: remove when we drop support for IE11
- // We need because normalize-url is distributed without
- // any kind of transpilation
- // More info: https://github.com/elastic/kibana/pull/35804
- {
- test: /\.js$/,
- include: /[\/\\]node_modules[\/\\]normalize-url[\/\\]/,
- exclude: /[\/\\]node_modules[\/\\]normalize-url[\/\\](.+?[\/\\])*node_modules[\/\\]/,
- },
- ],
- // Self calling function with the equivalent logic
- // from maybeAddCacheLoader one from base optimizer
- use: ((babelLoaderCacheDirPath, loaders) => {
- return [
- {
- loader: 'cache-loader',
- options: {
- cacheContext: fromRoot('.'),
- cacheDirectory: babelLoaderCacheDirPath,
- readOnly: process.env.KBN_CACHE_LOADER_WRITABLE ? false : IS_KIBANA_DISTRIBUTABLE,
- },
- },
- ...loaders,
- ];
- })(babelLoaderCacheDir, [
- {
- loader: 'thread-loader',
- options: threadLoaderPoolConfig,
- },
- {
- loader: 'babel-loader',
- options: {
- babelrc: false,
- presets: [BABEL_PRESET_PATH],
- },
- },
- ]),
- },
- {
- test: /\.(html|tmpl)$/,
- loader: 'raw-loader',
- },
- {
- test: /\.css$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader'],
- },
- {
- test: /\.png$/,
- loader: 'url-loader',
- },
- {
- test: /\.(woff|woff2|ttf|eot|svg|ico)(\?|$)/,
- loader: 'file-loader',
- },
- ],
- noParse: dllNoParseRules,
- },
- plugins: [
- new webpack.DllPlugin({
- context: dllContext,
- name: dllBundleName,
- path: dllManifestPath,
- }),
- new MiniCssExtractPlugin({
- filename: dllStyleFilename,
- }),
- ...getValidateSyntaxPlugins(),
- ],
- // Single runtime for the dll bundles which assures that common transient dependencies won't be evaluated twice.
- // The module cache will be shared, even when module code may be duplicated across chunks.
- optimization: {
- runtimeChunk: {
- name: 'vendors_runtime',
- },
- },
- performance: {
- // NOTE: we are disabling this as those hints
- // are more tailored for the final bundles result
- // and not for the webpack compilations performance itself
- hints: false,
- },
- externals: {
- ...UiSharedDeps.externals,
- },
- };
-}
-
-function extendRawConfig(rawConfig) {
- // Build all extended configs from raw config
- const dllAlias = rawConfig.uiBundles.getAliases();
- const dllValidateSyntax = rawConfig.uiBundles.shouldValidateSyntaxOfNodeModules();
- const dllNoParseRules = rawConfig.uiBundles.getWebpackNoParseRules();
- const dllDevMode = rawConfig.uiBundles.isDevMode();
- const dllContext = rawConfig.context;
- const dllChunks = rawConfig.chunks;
- const dllEntry = {};
- const dllEntryName = rawConfig.entryName;
- const dllBundleName = rawConfig.dllName;
- const dllManifestName = rawConfig.dllName;
- const dllStyleName = rawConfig.styleName;
- const dllEntryExt = rawConfig.entryExt;
- const dllBundleExt = rawConfig.dllExt;
- const dllManifestExt = rawConfig.manifestExt;
- const dllStyleExt = rawConfig.styleExt;
- const dllOutputPath = rawConfig.outputPath;
- const dllPublicPath = rawConfig.publicPath;
- const dllBundleFilename = `${dllBundleName}${dllBundleExt}`;
- const dllManifestPath = `${dllOutputPath}/${dllManifestName}${dllManifestExt}`;
- const dllStyleFilename = `${dllStyleName}${dllStyleExt}`;
- const babelLoaderCacheDir = rawConfig.babelLoaderCacheDir;
- const threadLoaderPoolConfig = rawConfig.threadLoaderPoolConfig;
-
- // Create webpack entry object key with the provided dllEntryName
- dllChunks.reduce((dllEntryObj, chunk) => {
- dllEntryObj[`${dllEntryName}${chunk}`] = [
- `${dllOutputPath}/${dllEntryName}${chunk}${dllEntryExt}`,
- ];
- return dllEntryObj;
- }, dllEntry);
-
- // Export dll config map
- return {
- dllAlias,
- dllValidateSyntax,
- dllNoParseRules,
- dllDevMode,
- dllContext,
- dllEntry,
- dllOutputPath,
- dllPublicPath,
- dllBundleName,
- dllBundleFilename,
- dllStyleFilename,
- dllManifestPath,
- babelLoaderCacheDir,
- threadLoaderPoolConfig,
- };
-}
-
-function common(config) {
- return webpackMerge(generateDLL(config));
-}
-
-function optimized() {
- return webpackMerge({
- mode: 'production',
- optimization: {
- minimizer: [
- new TerserPlugin({
- // NOTE: we should not enable that option for now
- // Since 2.0.0 terser-webpack-plugin is using jest-worker
- // to run tasks in a pool of workers. Currently it looks like
- // is requiring too much memory and break on large entry points
- // compilations (like this) one. Also the gain we have enabling
- // that option was barely noticed.
- // https://github.com/webpack-contrib/terser-webpack-plugin/issues/143
- parallel: false,
- sourceMap: false,
- cache: false,
- extractComments: false,
- terserOptions: {
- compress: false,
- mangle: false,
- },
- }),
- ],
- },
- });
-}
-
-function unoptimized() {
- return webpackMerge({
- mode: 'development',
- });
-}
-
-export function configModel(rawConfig = {}) {
- const config = extendRawConfig(rawConfig);
-
- if (config.dllDevMode) {
- return webpackMerge(common(config), unoptimized());
- }
-
- return webpackMerge(common(config), optimized());
-}
diff --git a/src/optimize/dynamic_dll_plugin/dll_entry_template.js b/src/optimize/dynamic_dll_plugin/dll_entry_template.js
deleted file mode 100644
index 351bed4e591ba..0000000000000
--- a/src/optimize/dynamic_dll_plugin/dll_entry_template.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export function dllEntryTemplate(requirePaths = []) {
- return requirePaths
- .map((path) => `require('${path}');`)
- .sort()
- .join('\n');
-}
-
-export function dllEntryFileContentStringToArray(content = '') {
- return content.split('\n');
-}
-
-export function dllEntryFileContentArrayToString(content = []) {
- return content.join('\n');
-}
-
-export function dllMergeAllEntryFilesContent(content = []) {
- return content.join('\n').split('\n').sort().join('\n');
-}
diff --git a/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js b/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js
deleted file mode 100644
index fb6f6e097b5cd..0000000000000
--- a/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { DllCompiler } from './dll_compiler';
-import { notInNodeModulesOrWebpackShims, inPluginNodeModules } from './dll_allowed_modules';
-import { IS_KIBANA_DISTRIBUTABLE } from '../../legacy/utils';
-import { dllEntryTemplate } from './dll_entry_template';
-import RawModule from 'webpack/lib/RawModule';
-import webpack from 'webpack';
-import path from 'path';
-import normalizePosixPath from 'normalize-path';
-import fs from 'fs';
-import { promisify } from 'util';
-
-const realPathAsync = promisify(fs.realpath);
-const DLL_ENTRY_STUB_MODULE_TYPE = 'javascript/dll-entry-stub';
-
-export class DynamicDllPlugin {
- constructor({ uiBundles, threadLoaderPoolConfig, logWithMetadata, maxCompilations = 1 }) {
- this.logWithMetadata = logWithMetadata || (() => null);
- this.dllCompiler = new DllCompiler(uiBundles, threadLoaderPoolConfig, logWithMetadata);
- this.entryPaths = dllEntryTemplate();
- this.afterCompilationEntryPaths = dllEntryTemplate();
- this.maxCompilations = maxCompilations;
- this.performedCompilations = 0;
- this.forceDLLCreationFlag = !!(process && process.env && process.env.FORCE_DLL_CREATION);
- }
-
- async init() {
- await this.dllCompiler.init();
- this.entryPaths = await this.dllCompiler.readEntryFiles();
- }
-
- apply(compiler) {
- // Just register the init basic hooks
- // in order to run the init function
- this.registerInitBasicHooks(compiler);
- // The dll reference should always be bind to the
- // main webpack config.
- this.bindDllReferencePlugin(compiler);
-
- // Verify if we must init and run the dynamic dll plugin tasks.
- // We must run it every time we are not under a distributable env
- if (!this.mustRunDynamicDllPluginTasks()) {
- return;
- }
-
- // This call init all the DynamicDllPlugin tasks
- // as it attaches the plugin to the main webpack
- // lifecycle hooks needed to perform the logic
- this.registerTasksHooks(compiler);
- }
-
- bindDllReferencePlugin(compiler) {
- const rawDllConfig = this.dllCompiler.rawDllConfig;
- const dllContext = rawDllConfig.context;
- const dllManifestPaths = this.dllCompiler.getManifestPaths();
-
- dllManifestPaths.forEach((dllChunkManifestPath) => {
- new webpack.DllReferencePlugin({
- context: dllContext,
- manifest: dllChunkManifestPath,
- }).apply(compiler);
- });
- }
-
- registerInitBasicHooks(compiler) {
- this.registerRunHook(compiler);
- this.registerWatchRunHook(compiler);
- }
-
- registerTasksHooks(compiler) {
- this.logWithMetadata(
- ['info', 'optimize:dynamic_dll_plugin'],
- 'Started dynamic dll plugin tasks'
- );
- this.registerBeforeCompileHook(compiler);
- this.registerCompilationHook(compiler);
- this.registerDoneHook(compiler);
- }
-
- registerRunHook(compiler) {
- compiler.hooks.run.tapPromise('DynamicDllPlugin', async () => {
- await this.init();
- });
- }
-
- registerWatchRunHook(compiler) {
- compiler.hooks.watchRun.tapPromise('DynamicDllPlugin', async () => {
- await this.init();
- });
- }
-
- registerBeforeCompileHook(compiler) {
- compiler.hooks.beforeCompile.tapPromise('DynamicDllPlugin', async ({ normalModuleFactory }) => {
- normalModuleFactory.hooks.factory.tap('DynamicDllPlugin', (actualFactory) => (params, cb) => {
- // This is used in order to avoid the cache for DLL modules
- // resolved from other dependencies
- normalModuleFactory.cachePredicate = (module) =>
- !(module.stubType === DLL_ENTRY_STUB_MODULE_TYPE);
-
- // Overrides the normalModuleFactory module creation behaviour
- // in order to understand the modules we need to add to the DLL
- actualFactory(params, (error, module) => {
- if (error || !module) {
- cb(error, module);
- } else {
- this.mapNormalModule(module).then(
- (m = module) => cb(undefined, m),
- (error) => cb(error)
- );
- }
- });
- });
- });
- }
-
- registerCompilationHook(compiler) {
- compiler.hooks.compilation.tap('DynamicDllPlugin', (compilation) => {
- compilation.hooks.needAdditionalPass.tap('DynamicDllPlugin', () => {
- // Run the procedures in order to execute our dll compilation
- // The process is very straightforward in it's conception:
- //
- // * 1 - loop through every compilation module in order to start building
- // the dll entry paths arrays and assume it is the new entry paths
- // * 1.1 - start from adding the modules already included into the dll, if any.
- // * 1.2 - adding the new discovered stub modules
- // * 1.3 - check if the module added to the entry path is from node_modules or
- // webpackShims, otherwise throw an error.
- // * 1.3.1 - for the entry path modules coming from webpackShims search for every
- // require statements inside of them
- // * 1.3.2 - discard the ones that are not js dependencies
- // * 1.3.3 - add those new discovered dependencies inside the webpackShims to the
- // entry paths array
- // * 2 - compare the built entry paths and compares it to the old one (if any)
- // * 3 - runs a new dll compilation in case there is none old entry paths or if the
- // new built one differs from the old one.
- //
- const rawDllConfig = this.dllCompiler.rawDllConfig;
- const dllContext = rawDllConfig.context;
- const dllOutputPath = rawDllConfig.outputPath;
- const requiresMap = {};
-
- for (const module of compilation.modules) {
- // re-include requires for modules already handled by the dll
- if (module.delegateData) {
- const absoluteResource = path.resolve(dllContext, module.userRequest);
- if (
- absoluteResource.includes('node_modules') ||
- absoluteResource.includes('webpackShims')
- ) {
- // NOTE: normalizePosixPath is been used as we only want to have posix
- // paths inside our final dll entry file
- requiresMap[
- normalizePosixPath(path.relative(dllOutputPath, absoluteResource))
- ] = true;
- }
- }
-
- // include requires for modules that need to be added to the dll
- if (module.stubType === DLL_ENTRY_STUB_MODULE_TYPE) {
- requiresMap[
- normalizePosixPath(path.relative(dllOutputPath, module.stubResource))
- ] = true;
- }
- }
-
- // Sort and join all the discovered require deps
- // in order to create a consistent entry file
- this.afterCompilationEntryPaths = dllEntryTemplate(Object.keys(requiresMap));
- // The dll compilation will run if on of the following conditions return true:
- // 1 - the new generated entry paths are different from the
- // old ones
- // 2 - if no dll bundle is yet created
- // 3 - if this.forceDLLCreationFlag were set from the node env var FORCE_DLL_CREATION and
- // we are not running over the distributable. If we are running under the watch optimizer,
- // this.forceDLLCreationFlag will only be applied in the very first execution,
- // then will be set to false
- compilation.needsDLLCompilation =
- this.afterCompilationEntryPaths !== this.entryPaths ||
- !this.dllCompiler.dllsExistsSync() ||
- (this.isToForceDLLCreation() && this.performedCompilations === 0);
- this.entryPaths = this.afterCompilationEntryPaths;
-
- // Only run this info log in the first performed dll compilation
- // per each execution run
- if (this.performedCompilations === 0) {
- this.logWithMetadata(
- ['info', 'optimize:dynamic_dll_plugin'],
- compilation.needsDLLCompilation
- ? 'Need to compile the client vendors dll'
- : 'No need to compile client vendors dll'
- );
- }
-
- return compilation.needsDLLCompilation;
- });
- });
- }
-
- registerDoneHook(compiler) {
- compiler.hooks.done.tapPromise('DynamicDllPlugin', async (stats) => {
- if (stats.compilation.needsDLLCompilation) {
- // Run the dlls compiler and increment
- // the performed compilations
- //
- // NOTE: check the need for this extra try/catch after upgrading
- // past webpack v4.29.3. For now it is needed so we can log the error
- // otherwise the error log we'll get will be something like: [fatal] [object Object]
- try {
- await this.runDLLCompiler(compiler);
- } catch (error) {
- this.logWithMetadata(['error', 'optimize:dynamic_dll_plugin'], error.message);
- throw error;
- }
-
- return;
- }
-
- this.performedCompilations = 0;
- // reset this flag var set from the node env FORCE_DLL_CREATION on init,
- // has the force_dll_creation is only valid for the very first run
- if (this.forceDLLCreationFlag) {
- this.forceDLLCreationFlag = false;
- }
- this.logWithMetadata(
- ['info', 'optimize:dynamic_dll_plugin'],
- 'Finished all dynamic dll plugin tasks'
- );
- });
- }
-
- isToForceDLLCreation() {
- return this.forceDLLCreationFlag;
- }
-
- mustRunDynamicDllPluginTasks() {
- return !IS_KIBANA_DISTRIBUTABLE || this.isToForceDLLCreation();
- }
-
- async mapNormalModule(module) {
- // ignore anything that doesn't have a resource (ignored) or is already delegating to the DLL
- if (!module.resource || module.delegateData) {
- return;
- }
-
- // ignore anything that needs special loaders or config
- if (module.request.includes('!') || module.request.includes('?')) {
- return;
- }
-
- // ignore files that are not in node_modules
- if (notInNodeModulesOrWebpackShims(module.resource)) {
- return;
- }
-
- // also ignore files that are symlinked into node_modules, but only
- // do the `realpath` call after checking the plain resource path
- if (notInNodeModulesOrWebpackShims(await realPathAsync(module.resource))) {
- return;
- }
-
- const dirs = module.resource.split(path.sep);
- const nodeModuleName = dirs[dirs.lastIndexOf('node_modules') + 1];
-
- // ignore webpack loader modules
- if (nodeModuleName.endsWith('-loader')) {
- return;
- }
-
- // ignore modules from plugins
- if (inPluginNodeModules(module.resource)) {
- return;
- }
-
- // also ignore files that are symlinked into plugins node_modules, but only
- // do the `realpath` call after checking the plain resource path
- if (inPluginNodeModules(await realPathAsync(module.resource))) {
- return;
- }
-
- // This is a StubModule (as a RawModule) in order
- // to mimic the missing modules from the DLL and
- // also hold useful metadata
- const stubModule = new RawModule(
- `/* pending dll entry */`,
- `dll pending:${module.resource}`,
- module.resource
- );
- stubModule.stubType = DLL_ENTRY_STUB_MODULE_TYPE;
- stubModule.stubResource = module.resource;
- stubModule.stubOriginalModule = module;
-
- return stubModule;
- }
-
- async assertMaxCompilations() {
- // Logic to run the max compilation requirements.
- // Only enable this for CI builds in order to ensure
- // we have an healthy dll ecosystem.
- if (this.performedCompilations === this.maxCompilations) {
- throw new Error(
- 'All the allowed dll compilations were already performed and one more is needed which is not possible'
- );
- }
- }
-
- async runDLLCompiler(mainCompiler) {
- const runCompilerErrors = [];
-
- try {
- await this.dllCompiler.run(this.entryPaths);
- } catch (e) {
- runCompilerErrors.push(e);
- }
-
- try {
- await this.assertMaxCompilations();
- } catch (e) {
- runCompilerErrors.push(e);
- }
-
- // We need to purge the cache into the inputFileSystem
- // for every single built in previous compilation
- // that we rely in next ones.
- this.dllCompiler
- .getManifestPaths()
- .forEach((chunkDllManifestPath) => mainCompiler.inputFileSystem.purge(chunkDllManifestPath));
-
- this.performedCompilations++;
-
- if (!runCompilerErrors.length) {
- return;
- }
-
- throw new Error(runCompilerErrors.join('\n-'));
- }
-}
diff --git a/src/optimize/dynamic_dll_plugin/index.js b/src/optimize/dynamic_dll_plugin/index.js
deleted file mode 100644
index 347811b5356b7..0000000000000
--- a/src/optimize/dynamic_dll_plugin/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export { DynamicDllPlugin } from './dynamic_dll_plugin';
-export { DllCompiler } from './dll_compiler';
diff --git a/src/optimize/optimize_mixin.ts b/src/optimize/optimize_mixin.ts
index 9a3f08e2f667e..947c918a567f5 100644
--- a/src/optimize/optimize_mixin.ts
+++ b/src/optimize/optimize_mixin.ts
@@ -22,8 +22,6 @@ import Hapi from 'hapi';
// @ts-ignore not TS yet
import FsOptimizer from './fs_optimizer';
import { createBundlesRoute } from './bundles_route';
-// @ts-ignore not TS yet
-import { DllCompiler } from './dynamic_dll_plugin';
import { fromRoot } from '../core/server/utils';
import { getNpUiPluginPublicDirs } from './np_ui_plugin_public_dirs';
import KbnServer, { KibanaConfig } from '../legacy/server/kbn_server';
@@ -40,7 +38,7 @@ export const optimizeMixin = async (
// bundles in a "middleware" style.
//
// the server listening on 5601 may be restarted a number of times, depending
- // on the watch setup managed by the cli. It proxies all bundles/* and built_assets/dlls/*
+ // on the watch setup managed by the cli. It proxies all bundles/*
// requests to the other server. The server on 5602 is long running, in order
// to prevent complete rebuilds of the optimize content.
const watch = config.get('optimize.watch');
@@ -53,7 +51,6 @@ export const optimizeMixin = async (
server.route(
createBundlesRoute({
regularBundlesPath: uiBundles.getWorkingDir(),
- dllBundlesPath: DllCompiler.getRawDllConfig().outputPath,
basePublicPath: config.get('server.basePath'),
builtCssPath: fromRoot('built_assets/css'),
npUiPluginPublicDirs: getNpUiPluginPublicDirs(kbnServer),
diff --git a/src/optimize/watch/optmzr_role.js b/src/optimize/watch/optmzr_role.js
index ba8007e1065b4..0057c04219ec6 100644
--- a/src/optimize/watch/optmzr_role.js
+++ b/src/optimize/watch/optmzr_role.js
@@ -17,12 +17,8 @@
* under the License.
*/
-import { resolve } from 'path';
-
import WatchServer from './watch_server';
import WatchOptimizer, { STATUS } from './watch_optimizer';
-import { DllCompiler } from '../dynamic_dll_plugin';
-import { WatchCache } from './watch_cache';
import { getNpUiPluginPublicDirs } from '../np_ui_plugin_public_dirs';
export default async (kbnServer, kibanaHapiServer, config) => {
@@ -36,12 +32,6 @@ export default async (kbnServer, kibanaHapiServer, config) => {
sourceMaps: config.get('optimize.sourceMaps'),
workers: config.get('optimize.workers'),
prebuild: config.get('optimize.watchPrebuild'),
- watchCache: new WatchCache({
- logWithMetadata,
- outputPath: config.get('path.data'),
- dllsPath: DllCompiler.getRawDllConfig().outputPath,
- cachePath: resolve(kbnServer.uiBundles.getCacheDirectory(), '../'),
- }),
});
const server = new WatchServer(
diff --git a/src/optimize/watch/watch.js b/src/optimize/watch/watch.js
index a284da11f294f..7774577fb7677 100644
--- a/src/optimize/watch/watch.js
+++ b/src/optimize/watch/watch.js
@@ -32,7 +32,7 @@ export default async (kbnServer) => {
* while the optimizer is running
*
* server: this process runs the entire kibana server and proxies
- * all requests for /bundles/* or /built_assets/dlls/* to the optmzr process
+ * all requests for /bundles/* to the optmzr process
*
* @param {string} process.env.kbnWorkerType
*/
diff --git a/src/optimize/watch/watch_cache.ts b/src/optimize/watch/watch_cache.ts
deleted file mode 100644
index 40bd1d6075f47..0000000000000
--- a/src/optimize/watch/watch_cache.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { createHash } from 'crypto';
-import { readFile, writeFile, readdir, unlink, rmdir } from 'fs';
-import { resolve } from 'path';
-import { promisify } from 'util';
-import path from 'path';
-import del from 'del';
-import normalizePosixPath from 'normalize-path';
-
-const readAsync = promisify(readFile);
-const writeAsync = promisify(writeFile);
-const readdirAsync = promisify(readdir);
-const unlinkAsync = promisify(unlink);
-const rmdirAsync = promisify(rmdir);
-
-interface Params {
- logWithMetadata: (tags: string[], message: string, metadata?: { [key: string]: any }) => void;
- outputPath: string;
- dllsPath: string;
- cachePath: string;
-}
-
-interface WatchCacheStateContent {
- optimizerConfigSha?: string;
- yarnLockSha?: string;
-}
-
-export class WatchCache {
- private readonly logWithMetadata: Params['logWithMetadata'];
- private readonly outputPath: Params['outputPath'];
- private readonly dllsPath: Params['dllsPath'];
- private readonly cachePath: Params['cachePath'];
- private readonly cacheState: WatchCacheStateContent;
- private statePath: string;
- private diskCacheState: WatchCacheStateContent;
- private isInitialized: boolean;
-
- constructor(params: Params) {
- this.logWithMetadata = params.logWithMetadata;
- this.outputPath = params.outputPath;
- this.dllsPath = params.dllsPath;
- this.cachePath = params.cachePath;
-
- this.isInitialized = false;
- this.statePath = '';
- this.cacheState = {};
- this.diskCacheState = {};
- this.cacheState.yarnLockSha = '';
- this.cacheState.optimizerConfigSha = '';
- }
-
- public async tryInit() {
- if (!this.isInitialized) {
- this.statePath = resolve(this.outputPath, 'watch_optimizer_cache_state.json');
- this.diskCacheState = await this.read();
- this.cacheState.yarnLockSha = await this.buildYarnLockSha();
- this.cacheState.optimizerConfigSha = await this.buildOptimizerConfigSha();
- this.isInitialized = true;
- }
- }
-
- public async tryReset() {
- await this.tryInit();
-
- if (!this.isResetNeeded()) {
- return;
- }
-
- await this.reset();
- }
-
- public async reset() {
- this.logWithMetadata(['info', 'optimize:watch_cache'], 'The optimizer watch cache will reset');
-
- // start by deleting the state file to lower the
- // amount of time that another process might be able to
- // successfully read it once we decide to delete it
- await del(this.statePath, { force: true });
-
- // delete everything in optimize/.cache directory
- await recursiveDelete(normalizePosixPath(this.cachePath));
-
- // delete dlls
- await del(this.dllsPath);
-
- // re-write new cache state file
- await this.write();
-
- this.logWithMetadata(['info', 'optimize:watch_cache'], 'The optimizer watch cache has reset');
- }
-
- private async buildShaWithMultipleFiles(filePaths: string[]) {
- const shaHash = createHash('sha1');
-
- for (const filePath of filePaths) {
- try {
- shaHash.update(await readAsync(filePath, 'utf8'), 'utf8');
- } catch (e) {
- /* no-op */
- }
- }
-
- return shaHash.digest('hex');
- }
-
- private async buildYarnLockSha() {
- const kibanaYarnLock = resolve(__dirname, '../../../yarn.lock');
-
- return await this.buildShaWithMultipleFiles([kibanaYarnLock]);
- }
-
- private async buildOptimizerConfigSha() {
- const baseOptimizer = resolve(__dirname, '../base_optimizer.js');
- const dynamicDllConfigModel = resolve(__dirname, '../dynamic_dll_plugin/dll_config_model.js');
- const dynamicDllPlugin = resolve(__dirname, '../dynamic_dll_plugin/dynamic_dll_plugin.js');
-
- return await this.buildShaWithMultipleFiles([
- baseOptimizer,
- dynamicDllConfigModel,
- dynamicDllPlugin,
- ]);
- }
-
- private isResetNeeded() {
- return this.hasYarnLockChanged() || this.hasOptimizerConfigChanged();
- }
-
- private hasYarnLockChanged() {
- return this.cacheState.yarnLockSha !== this.diskCacheState.yarnLockSha;
- }
-
- private hasOptimizerConfigChanged() {
- return this.cacheState.optimizerConfigSha !== this.diskCacheState.optimizerConfigSha;
- }
-
- private async write() {
- await writeAsync(this.statePath, JSON.stringify(this.cacheState, null, 2), 'utf8');
- this.diskCacheState = this.cacheState;
- }
-
- private async read(): Promise {
- try {
- return JSON.parse(await readAsync(this.statePath, 'utf8'));
- } catch (error) {
- return {};
- }
- }
-}
-
-/**
- * Recursively deletes a folder. This is a workaround for a bug in `del` where
- * very large folders (with 84K+ files) cause a stack overflow.
- */
-async function recursiveDelete(directory: string) {
- try {
- const entries = await readdirAsync(directory, { withFileTypes: true });
-
- await Promise.all(
- entries.map((entry) => {
- const absolutePath = path.join(directory, entry.name);
- return entry.isDirectory() ? recursiveDelete(absolutePath) : unlinkAsync(absolutePath);
- })
- );
-
- return rmdirAsync(directory);
- } catch (error) {
- if (error.code !== 'ENOENT') {
- throw error;
- }
- }
-}
diff --git a/src/optimize/watch/watch_optimizer.js b/src/optimize/watch/watch_optimizer.js
index 816185e544ab5..000c03ffb34fe 100644
--- a/src/optimize/watch/watch_optimizer.js
+++ b/src/optimize/watch/watch_optimizer.js
@@ -19,7 +19,6 @@
import BaseOptimizer from '../base_optimizer';
import { createBundlesRoute } from '../bundles_route';
-import { DllCompiler } from '../dynamic_dll_plugin';
import { fromRoot } from '../../core/server/utils';
import * as Rx from 'rxjs';
import { mergeMap, take } from 'rxjs/operators';
@@ -35,7 +34,6 @@ export default class WatchOptimizer extends BaseOptimizer {
constructor(opts) {
super(opts);
this.prebuild = opts.prebuild || false;
- this.watchCache = opts.watchCache;
this.status$ = new Rx.ReplaySubject(1);
}
@@ -43,9 +41,6 @@ export default class WatchOptimizer extends BaseOptimizer {
this.initializing = true;
this.initialBuildComplete = false;
- // try reset the watch optimizer cache
- await this.watchCache.tryReset();
-
// log status changes
this.status$.subscribe(this.onStatusChangeHandler);
await this.uiBundles.resetBundleDir();
@@ -120,7 +115,6 @@ export default class WatchOptimizer extends BaseOptimizer {
npUiPluginPublicDirs: npUiPluginPublicDirs,
buildHash,
regularBundlesPath: this.compiler.outputPath,
- dllBundlesPath: DllCompiler.getRawDllConfig().outputPath,
basePublicPath: basePath,
builtCssPath: fromRoot('built_assets/css'),
})
diff --git a/src/plugins/dashboard/README.asciidoc b/src/plugins/dashboard/README.asciidoc
new file mode 100644
index 0000000000000..78163b14c14d6
--- /dev/null
+++ b/src/plugins/dashboard/README.asciidoc
@@ -0,0 +1,5 @@
+[[kibana-dashboard-plugin]]
+== Dashboard plugin
+
+- Registers the dashboard application.
+- Adds a dashboard embeddable that can be used in other applications.
\ No newline at end of file
diff --git a/src/plugins/dashboard/server/saved_objects/dashboard.ts b/src/plugins/dashboard/server/saved_objects/dashboard.ts
index 14d2c822a421e..850b2470dd475 100644
--- a/src/plugins/dashboard/server/saved_objects/dashboard.ts
+++ b/src/plugins/dashboard/server/saved_objects/dashboard.ts
@@ -44,21 +44,23 @@ export const dashboardSavedObjectType: SavedObjectsType = {
mappings: {
properties: {
description: { type: 'text' },
- hits: { type: 'integer' },
- kibanaSavedObjectMeta: { properties: { searchSourceJSON: { type: 'text' } } },
- optionsJSON: { type: 'text' },
- panelsJSON: { type: 'text' },
+ hits: { type: 'integer', index: false, doc_values: false },
+ kibanaSavedObjectMeta: {
+ properties: { searchSourceJSON: { type: 'text', index: false, doc_values: false } },
+ },
+ optionsJSON: { type: 'text', index: false, doc_values: false },
+ panelsJSON: { type: 'text', index: false, doc_values: false },
refreshInterval: {
properties: {
- display: { type: 'keyword' },
- pause: { type: 'boolean' },
- section: { type: 'integer' },
- value: { type: 'integer' },
+ display: { type: 'keyword', index: false, doc_values: false },
+ pause: { type: 'boolean', index: false, doc_values: false },
+ section: { type: 'integer', index: false, doc_values: false },
+ value: { type: 'integer', index: false, doc_values: false },
},
},
- timeFrom: { type: 'keyword' },
- timeRestore: { type: 'boolean' },
- timeTo: { type: 'keyword' },
+ timeFrom: { type: 'keyword', index: false, doc_values: false },
+ timeRestore: { type: 'boolean', index: false, doc_values: false },
+ timeTo: { type: 'keyword', index: false, doc_values: false },
title: { type: 'text' },
version: { type: 'integer' },
},
diff --git a/src/plugins/discover/public/application/_discover.scss b/src/plugins/discover/public/application/_discover.scss
index 1aaa0a24357ed..69df2a75b8d75 100644
--- a/src/plugins/discover/public/application/_discover.scss
+++ b/src/plugins/discover/public/application/_discover.scss
@@ -103,3 +103,15 @@ discover-app {
right: $euiSizeM;
top: $euiSizeXS;
}
+
+[fixed-scroll] {
+ overflow-x: auto;
+ padding-bottom: 0;
+
+ + .fixed-scroll-scroller {
+ position: fixed;
+ bottom: 0;
+ overflow-x: auto;
+ overflow-y: hidden;
+ }
+}
diff --git a/src/plugins/discover/public/application/_hacks.scss b/src/plugins/discover/public/application/_hacks.scss
deleted file mode 100644
index 9bbe9cd14fd91..0000000000000
--- a/src/plugins/discover/public/application/_hacks.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-// SASSTODO: the classname is dynamically generated with ng-class
-.tab-discover {
- overflow: hidden;
-}
diff --git a/src/plugins/discover/public/application/_mixins.scss b/src/plugins/discover/public/application/_mixins.scss
deleted file mode 100644
index 100f81ae92bf0..0000000000000
--- a/src/plugins/discover/public/application/_mixins.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
-* Style ES document _source in table view key:value
-* Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted
-* row in the Context Log.
-*/
-@mixin dscDocSourceStyle {
- dl.source {
- margin-bottom: 0;
- line-height:2em;
- word-break: break-word;
-
- dt, dd {
- display: inline;
- }
-
- dt {
- background-color: transparentize(shade($euiColorPrimary, 20%), .9);
- color: $euiTextColor;
- padding: ($euiSizeXS / 2) $euiSizeXS;
- margin-right: $euiSizeXS;
- word-break: normal;
- border-radius: $euiBorderRadius;
- }
- }
-}
-
-
diff --git a/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss b/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss
index 3e30214acd2a9..7d05171622e7b 100644
--- a/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss
+++ b/src/plugins/discover/public/application/angular/doc_table/_doc_table.scss
@@ -27,7 +27,6 @@ doc-table {
}
.kbnDocTable {
- @include dscDocSourceStyle;
font-size: $euiFontSizeXS;
th {
@@ -40,6 +39,35 @@ doc-table {
}
}
+.kbn-table,
+.kbnDocTable {
+ /**
+ * Style ES document _source in table view key:value
+ * Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted
+ * row in the Context Log.
+ */
+
+ dl.source {
+ margin-bottom: 0;
+ line-height: 2em;
+ word-break: break-word;
+
+ dt,
+ dd {
+ display: inline;
+ }
+
+ dt {
+ background-color: transparentize(shade($euiColorPrimary, 20%), 0.9);
+ color: $euiTextColor;
+ padding: ($euiSizeXS / 2) $euiSizeXS;
+ margin-right: $euiSizeXS;
+ word-break: normal;
+ border-radius: $euiBorderRadius;
+ }
+ }
+}
+
.kbnDocTable__row {
td {
position: relative;
@@ -80,3 +108,50 @@ doc-table {
text-align: center;
}
+.truncate-by-height {
+ overflow: hidden;
+}
+
+.table {
+ // Nesting
+ .table {
+ background-color: $euiColorEmptyShade;
+ }
+}
+
+.kbn-table {
+ // sub tables should not have a leading border
+ .table .table {
+ margin-bottom: 0;
+
+ tr:first-child > td {
+ border-top: none;
+ }
+
+ td.field-name {
+ font-weight: $euiFontWeightBold;
+ }
+ }
+}
+
+table {
+ th {
+ i.fa-sort {
+ color: $euiColorLightShade;
+ }
+
+ button.fa-sort-asc,
+ button.fa-sort-down,
+ i.fa-sort-asc,
+ i.fa-sort-down {
+ color: $euiColorPrimary;
+ }
+
+ button.fa-sort-desc,
+ button.fa-sort-up,
+ i.fa-sort-desc,
+ i.fa-sort-up {
+ color: $euiColorPrimary;
+ }
+ }
+}
diff --git a/src/plugins/discover/public/application/angular/doc_table/index.scss b/src/plugins/discover/public/application/angular/doc_table/index.scss
index 4e6cb83c5fe5a..3663d807851c4 100644
--- a/src/plugins/discover/public/application/angular/doc_table/index.scss
+++ b/src/plugins/discover/public/application/angular/doc_table/index.scss
@@ -1,4 +1,2 @@
-@import '../../mixins';
-
@import 'doc_table';
@import 'components/index';
diff --git a/src/plugins/discover/public/application/index.scss b/src/plugins/discover/public/application/index.scss
index aaec7ab387e96..5aa353828274c 100644
--- a/src/plugins/discover/public/application/index.scss
+++ b/src/plugins/discover/public/application/index.scss
@@ -1,13 +1,2 @@
-// Discover plugin styles
-@import 'mixins';
-@import 'discover';
-@import 'hacks';
-
-// Prefix all styles with "dsc" to avoid conflicts.
-// Examples
-// dscTable
-// dscTable__footer
-// monChart__legend--small
-// monChart__legend-isLoading
-
@import 'angular/index';
+@import 'discover';
diff --git a/src/plugins/discover/server/saved_objects/search.ts b/src/plugins/discover/server/saved_objects/search.ts
index 2348d89c4f4dd..c13550e543ab6 100644
--- a/src/plugins/discover/server/saved_objects/search.ts
+++ b/src/plugins/discover/server/saved_objects/search.ts
@@ -43,15 +43,15 @@ export const searchSavedObjectType: SavedObjectsType = {
},
mappings: {
properties: {
- columns: { type: 'keyword', index: false },
+ columns: { type: 'keyword', index: false, doc_values: false },
description: { type: 'text' },
- hits: { type: 'integer', index: false },
+ hits: { type: 'integer', index: false, doc_values: false },
kibanaSavedObjectMeta: {
properties: {
- searchSourceJSON: { type: 'text', index: false },
+ searchSourceJSON: { type: 'text', index: false, doc_values: false },
},
},
- sort: { type: 'keyword', index: false },
+ sort: { type: 'keyword', index: false, doc_values: false },
title: { type: 'text' },
version: { type: 'integer' },
},
diff --git a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap
index 2545bbcb5114d..9178d0e08f3e0 100644
--- a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap
+++ b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap
@@ -195,7 +195,7 @@ exports[`apmUiEnabled 1`] = `
- Centralize security events for interactive investigation in ready-to-go visualizations.
+ Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
}
footer={
@@ -212,7 +212,7 @@ exports[`apmUiEnabled 1`] = `
}
textAlign="left"
- title="Security"
+ title="SIEM + Endpoint Security"
titleSize="xs"
/>
@@ -461,7 +461,7 @@ exports[`isNewKibanaInstance 1`] = `
- Centralize security events for interactive investigation in ready-to-go visualizations.
+ Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
}
footer={
@@ -478,7 +478,7 @@ exports[`isNewKibanaInstance 1`] = `
}
textAlign="left"
- title="Security"
+ title="SIEM + Endpoint Security"
titleSize="xs"
/>
@@ -758,7 +758,7 @@ exports[`mlEnabled 1`] = `
- Centralize security events for interactive investigation in ready-to-go visualizations.
+ Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
}
footer={
@@ -775,7 +775,7 @@ exports[`mlEnabled 1`] = `
}
textAlign="left"
- title="Security"
+ title="SIEM + Endpoint Security"
titleSize="xs"
/>
@@ -1060,7 +1060,7 @@ exports[`render 1`] = `
- Centralize security events for interactive investigation in ready-to-go visualizations.
+ Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
}
footer={
@@ -1077,7 +1077,7 @@ exports[`render 1`] = `
}
textAlign="left"
- title="Security"
+ title="SIEM + Endpoint Security"
titleSize="xs"
/>
diff --git a/src/plugins/home/public/application/components/add_data.js b/src/plugins/home/public/application/components/add_data.js
index fa1327b3fcd08..c35b7b04932fb 100644
--- a/src/plugins/home/public/application/components/add_data.js
+++ b/src/plugins/home/public/application/components/add_data.js
@@ -81,12 +81,12 @@ const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => {
const siemData = {
title: intl.formatMessage({
id: 'home.addData.securitySolution.nameTitle',
- defaultMessage: 'Security',
+ defaultMessage: 'SIEM + Endpoint Security',
}),
description: intl.formatMessage({
id: 'home.addData.securitySolution.nameDescription',
defaultMessage:
- 'Centralize security events for interactive investigation in ready-to-go visualizations.',
+ 'Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.',
}),
ariaDescribedby: 'aria-describedby.addSiemButtonLabel',
};
diff --git a/src/plugins/kibana_legacy/public/paginate/_paginate.scss b/src/plugins/kibana_legacy/public/paginate/_paginate.scss
new file mode 100644
index 0000000000000..e9c1acaf9ee0d
--- /dev/null
+++ b/src/plugins/kibana_legacy/public/paginate/_paginate.scss
@@ -0,0 +1,57 @@
+paginate {
+ display: block;
+
+ paginate-controls {
+ display: flex;
+ align-items: center;
+ padding: $euiSizeXS $euiSizeXS $euiSizeS;
+ text-align: center;
+
+ .pagination-other-pages {
+ flex: 1 0 auto;
+ display: flex;
+ justify-content: center;
+ }
+
+ .pagination-other-pages-list {
+ flex: 0 0 auto;
+ display: flex;
+ justify-content: center;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+
+ > li {
+ flex: 0 0 auto;
+ user-select: none;
+
+ a {
+ text-decoration: none;
+ background-color: $euiColorLightestShade;
+ margin-left: $euiSizeXS / 2;
+ padding: $euiSizeS $euiSizeM;
+ }
+
+ a:hover {
+ text-decoration: underline;
+ }
+
+ &.active a {
+ text-decoration: none !important;
+ font-weight: $euiFontWeightBold;
+ color: $euiColorDarkShade;
+ cursor: default;
+ }
+ }
+ }
+
+ .pagination-size {
+ flex: 0 0 auto;
+
+ input[type=number] {
+ width: 3em;
+ }
+ }
+ }
+}
+
diff --git a/src/plugins/kibana_legacy/public/paginate/paginate.js b/src/plugins/kibana_legacy/public/paginate/paginate.js
index ea93a969d08c7..f424c33ba7b02 100644
--- a/src/plugins/kibana_legacy/public/paginate/paginate.js
+++ b/src/plugins/kibana_legacy/public/paginate/paginate.js
@@ -19,6 +19,7 @@
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
+import './_paginate.scss';
import paginateControlsTemplate from './paginate_controls.html';
export function PaginateDirectiveProvider($parse, $compile) {
diff --git a/src/plugins/timelion/public/_base.scss b/src/plugins/timelion/public/_base.scss
new file mode 100644
index 0000000000000..616ac9b3486e7
--- /dev/null
+++ b/src/plugins/timelion/public/_base.scss
@@ -0,0 +1,19 @@
+// Angular form states
+.ng-invalid {
+ &.ng-dirty,
+ &.ng-touched {
+ border-color: $euiColorDanger;
+ }
+}
+
+input[type='radio'],
+input[type='checkbox'],
+.radio,
+.checkbox {
+ &[disabled],
+ fieldset[disabled] & {
+ cursor: default;
+ opacity: .8;
+ }
+}
+
diff --git a/src/legacy/ui/public/styles/_legacy/_mixins.scss b/src/plugins/timelion/public/directives/_form.scss
similarity index 58%
rename from src/legacy/ui/public/styles/_legacy/_mixins.scss
rename to src/plugins/timelion/public/directives/_form.scss
index 2834f60555070..3fcf70700a864 100644
--- a/src/legacy/ui/public/styles/_legacy/_mixins.scss
+++ b/src/plugins/timelion/public/directives/_form.scss
@@ -1,23 +1,19 @@
-// These mixins are temporary helpers to consolidate styles of elements that
-// are not yet converted to use EUI.
-
-// DO NOT CONTINUE TO USE THESE MIXINS
-
-@mixin __legacyInputStyles__bad {
- &:not([type='range']) {
- appearance: none;
- }
+.form-control {
+ @include euiFontSizeS;
display: block;
width: 100%;
height: $euiFormControlCompressedHeight;
padding: $euiSizeXS $euiSizeM;
- @include euiFontSizeS;
border: $euiBorderThin;
background-color: $euiFormBackgroundColor;
color: $euiTextColor;
border-radius: $euiBorderRadius;
cursor: pointer;
+ &:not([type='range']) {
+ appearance: none;
+ }
+
&:focus {
border-color: $euiColorPrimary;
outline: none;
@@ -25,30 +21,16 @@
}
}
-@mixin __legacySelectStyles__bad {
+// sass-lint:disable-block no-qualifying-elements
+select.form-control {
// Makes the select arrow similar to EUI's arrowDown icon
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='#{hexToRGB($euiTextColor)}' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
+ background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"%3E%3Cpath fill="#{hexToRGB($euiTextColor)}" d="M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z"/%3E%3C/svg%3E');
background-size: $euiSize;
background-repeat: no-repeat;
background-position: calc(100% - #{$euiSizeS});
padding-right: $euiSizeXL;
-
- &::-ms-expand {
- display: none;
- }
-
- &:focus::-ms-value {
- color: $euiTextColor;
- background: transparent;
- }
}
-@mixin __legacyLabelStyles__bad {
- font-size: $euiFontSizeXS;
- font-weight: $euiFontWeightSemiBold;
- color: $euiTextColor;
-
- &[for] {
- cursor: pointer;
- }
+.fullWidth {
+ width: 100%;
}
diff --git a/src/plugins/timelion/public/directives/_index.scss b/src/plugins/timelion/public/directives/_index.scss
index cd46a1a0a369e..a407c1dfabdeb 100644
--- a/src/plugins/timelion/public/directives/_index.scss
+++ b/src/plugins/timelion/public/directives/_index.scss
@@ -3,3 +3,6 @@
@import './timelion_expression_suggestions/index';
@import './timelion_help/index';
@import './timelion_interval/index';
+@import './saved_object_finder';
+@import './form';
+
diff --git a/src/legacy/ui/public/styles/_legacy/components/_list_group_menu.scss b/src/plugins/timelion/public/directives/_saved_object_finder.scss
similarity index 85%
rename from src/legacy/ui/public/styles/_legacy/components/_list_group_menu.scss
rename to src/plugins/timelion/public/directives/_saved_object_finder.scss
index 3bac75cb19d9d..b97dace5e9e00 100644
--- a/src/legacy/ui/public/styles/_legacy/components/_list_group_menu.scss
+++ b/src/plugins/timelion/public/directives/_saved_object_finder.scss
@@ -1,7 +1,7 @@
.list-group-menu {
&.select-mode a {
- outline: none;
- color: tintOrShade($euiColorPrimary, 10%, 10%);
+ outline: none;
+ color: tintOrShade($euiColorPrimary, 10%, 10%);
}
.list-group-menu-item {
@@ -12,9 +12,11 @@
font-weight: bold;
background-color: $euiColorLightShade;
}
+
&:hover {
background-color: tintOrShade($euiColorPrimary, 90%, 90%);
}
+
li {
list-style: none;
color: tintOrShade($euiColorPrimary, 10%, 10%);
diff --git a/src/plugins/timelion/public/index.scss b/src/plugins/timelion/public/index.scss
index cf2a7859a505d..6bf7133287c51 100644
--- a/src/plugins/timelion/public/index.scss
+++ b/src/plugins/timelion/public/index.scss
@@ -8,4 +8,5 @@
// timChart__legend-isLoading
@import './app';
+@import './base';
@import './directives/index';
diff --git a/src/plugins/vis_type_table/public/agg_table/_agg_table.scss b/src/plugins/vis_type_table/public/agg_table/_agg_table.scss
index 0fffb21eab0fb..4bbc4eb034f8d 100644
--- a/src/plugins/vis_type_table/public/agg_table/_agg_table.scss
+++ b/src/plugins/vis_type_table/public/agg_table/_agg_table.scss
@@ -36,3 +36,7 @@ kbn-agg-table-group {
padding: 0;
}
}
+
+.small {
+ font-size: 0.9em !important;
+}
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.js b/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.js
index 438c071d74532..03b5af2572d94 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.js
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.js
@@ -21,7 +21,23 @@ import _ from 'lodash';
import { i18n } from '@kbn/i18n';
function getSeriId(seri) {
- return seri.id && seri.id.indexOf('.') !== -1 ? seri.id.split('.')[0] : seri.id;
+ if (!seri.id) {
+ return;
+ }
+ // Ideally the format should be either ID or "ID.SERIES"
+ // but for some values the SERIES components gets a bit more complex
+
+ // Float values are serialized as strings tuples (i.e. ['99.1']) rather than regular numbers (99.1)
+ // so the complete ids are in the format ID.['SERIES']: hence the specific brackets handler
+ const bracketsMarker = seri.id.indexOf('[');
+ if (bracketsMarker > -1) {
+ return seri.id.substring(0, bracketsMarker);
+ }
+ // Here's the dot check is enough
+ if (seri.id.indexOf('.') > -1) {
+ return seri.id.split('.')[0];
+ }
+ return seri.id;
}
const createSeriesFromParams = (cfg, seri) => {
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js b/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js
index 62ff873f28134..b46054f3cd983 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/point_series.test.js
@@ -20,6 +20,8 @@ import stackedSeries from '../../../fixtures/mock_data/date_histogram/_stacked_s
import { vislibPointSeriesTypes } from './point_series';
import percentileTestdata from './testdata_linechart_percentile.json';
import percentileTestdataResult from './testdata_linechart_percentile_result.json';
+import percentileTestdataFloatValue from './testdata_linechart_percentile_float_value.json';
+import percentileTestdataFloatValueResult from './testdata_linechart_percentile_float_value_result.json';
const maxBucketData = {
get: (prop) => {
@@ -215,18 +217,26 @@ describe('Point Series Config Type Class Test Suite', function () {
});
describe('line chart', function () {
- beforeEach(function () {
+ function prepareData({ cfg, data }) {
const percentileDataObj = {
get: (prop) => {
return maxBucketData[prop] || maxBucketData.data[prop] || null;
},
getLabels: () => [],
- data: percentileTestdata.data,
+ data: data,
};
- parsedConfig = vislibPointSeriesTypes.line(percentileTestdata.cfg, percentileDataObj);
- });
+ const parsedConfig = vislibPointSeriesTypes.line(cfg, percentileDataObj);
+ return parsedConfig;
+ }
+
it('should render a percentile line chart', function () {
- expect(JSON.stringify(parsedConfig)).toEqual(JSON.stringify(percentileTestdataResult));
+ const parsedConfig = prepareData(percentileTestdata);
+ expect(parsedConfig).toMatchObject(percentileTestdataResult);
+ });
+
+ it('should render a percentile line chart when value is float', function () {
+ const parsedConfig = prepareData(percentileTestdataFloatValue);
+ expect(parsedConfig).toMatchObject(percentileTestdataFloatValueResult);
});
});
});
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json
index 818d9133938fa..d52cb18727c05 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile.json
@@ -140,320 +140,320 @@
}
},
"yAxisLabel": "",
- "series": [
- {
- "id": "1.1",
- "rawId": "col-1-1.1",
- "label": "1st percentile of AvgTicketPrice",
- "values": [
- {
- "x": 1557460800000,
- "y": 116.33676605224609,
- "extraMetrics": [],
- "xRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 0,
- "row": 0,
- "value": 1557460800000
+ "hits": 2
+ },
+ "series": [
+ {
+ "id": "1.1",
+ "rawId": "col-1-1.1",
+ "label": "1st percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 116.33676605224609,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "yRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 1,
- "row": 0,
- "value": 116.33676605224609
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "parent": null,
- "series": "1st percentile of AvgTicketPrice",
- "seriesId": "col-1-1.1"
+ "column": 1,
+ "row": 0,
+ "value": 116.33676605224609
},
- {
- "x": 1557547200000,
- "y": 223,
- "extraMetrics": [],
- "xRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 0,
- "row": 1,
- "value": 1557547200000
+ "parent": null,
+ "series": "1st percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.1"
+ },
+ {
+ "x": 1557547200000,
+ "y": 223,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "yRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 1,
- "row": 1,
- "value": 223
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "parent": null,
- "series": "1st percentile of AvgTicketPrice",
- "seriesId": "col-1-1.1"
- }
- ]
- },
- {
- "id": "1.50",
- "rawId": "col-2-1.50",
- "label": "50th percentile of AvgTicketPrice",
- "values": [
- {
- "x": 1557460800000,
- "y": 658.8453063964844,
- "extraMetrics": [],
- "xRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 0,
- "row": 0,
- "value": 1557460800000
+ "column": 1,
+ "row": 1,
+ "value": 223
+ },
+ "parent": null,
+ "series": "1st percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.1"
+ }
+ ]
+ },
+ {
+ "id": "1.50",
+ "rawId": "col-2-1.50",
+ "label": "50th percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 658.8453063964844,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "yRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 2,
- "row": 0,
- "value": 658
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "parent": null,
- "series": "50th percentile of AvgTicketPrice",
- "seriesId": "col-2-1.50"
+ "column": 2,
+ "row": 0,
+ "value": 658
},
- {
- "x": 1557547200000,
- "y": 756,
- "extraMetrics": [],
- "xRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 0,
- "row": 1,
- "value": 1557547200000
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ },
+ {
+ "x": 1557547200000,
+ "y": 756,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "yRaw": {
- "table": {
- "columns": [
- {
- "id": "col-0-2",
- "name": "timestamp per day"
- },
- {
- "id": "col-1-1.1",
- "name": "1st percentile of AvgTicketPrice"
- },
- {
- "id": "col-2-1.50",
- "name": "50th percentile of AvgTicketPrice"
- }
- ],
- "rows": [
- {
- "col-0-2": 1557460800000,
- "col-1-1.1": 116,
- "col-2-1.50": 658
- },
- {
- "col-0-2": 1557547200000,
- "col-1-1.1": 223,
- "col-2-1.50": 756
- }
- ]
- },
- "column": 2,
- "row": 1,
- "value": 756.2283554077148
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
},
- "parent": null,
- "series": "50th percentile of AvgTicketPrice",
- "seriesId": "col-2-1.50"
- }
- ]
- }
- ],
- "hits": 2
- },
+ "column": 2,
+ "row": 1,
+ "value": 756.2283554077148
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ }
+ ]
+ }
+ ],
"type": "series",
"labels": [
"1st percentile of AvgTicketPrice",
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json
new file mode 100644
index 0000000000000..6e1a707229974
--- /dev/null
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value.json
@@ -0,0 +1,463 @@
+{
+ "cfg": {
+ "addLegend": true,
+ "addTimeMarker": false,
+ "addTooltip": true,
+ "categoryAxes": [
+ {
+ "id": "CategoryAxis-1",
+ "labels": {
+ "show": true,
+ "truncate": 100
+ },
+ "position": "bottom",
+ "scale": {
+ "type": "linear"
+ },
+ "show": true,
+ "style": {},
+ "title": {},
+ "type": "category"
+ }
+ ],
+ "dimensions": {
+ "x": {
+ "accessor": 0,
+ "format": {
+ "id": "date",
+ "params": {
+ "pattern": "YYYY-MM-DD"
+ }
+ },
+ "params": {
+ "date": true,
+ "interval": "P1D",
+ "format": "YYYY-MM-DD",
+ "bounds": {
+ "min": "2019-05-10T04:00:00.000Z",
+ "max": "2019-05-12T10:18:57.342Z"
+ }
+ },
+ "aggType": "date_histogram"
+ },
+ "y": [
+ {
+ "accessor": 1,
+ "format": {
+ "id": "number",
+ "params": {
+ "pattern": "$0,0.[00]"
+ }
+ },
+ "params": {},
+ "aggType": "percentiles"
+ },
+ {
+ "accessor": 2,
+ "format": {
+ "id": "number",
+ "params": {
+ "pattern": "$0,0.[00]"
+ }
+ },
+ "params": {},
+ "aggType": "percentiles"
+ }
+ ]
+ },
+ "grid": {
+ "categoryLines": false,
+ "style": {
+ "color": "#eee"
+ }
+ },
+ "legendPosition": "right",
+ "seriesParams": [
+ {
+ "data": {
+ "id": "1",
+ "label": "Percentiles of AvgTicketPrice"
+ },
+ "drawLinesBetweenPoints": true,
+ "interpolate": "cardinal",
+ "mode": "normal",
+ "show": "true",
+ "showCircles": true,
+ "type": "line",
+ "valueAxis": "ValueAxis-1"
+ }
+ ],
+ "times": [],
+ "type": "area",
+ "valueAxes": [
+ {
+ "id": "ValueAxis-1",
+ "labels": {
+ "filter": false,
+ "rotate": 0,
+ "show": true,
+ "truncate": 100
+ },
+ "name": "LeftAxis-1",
+ "position": "left",
+ "scale": {
+ "mode": "normal",
+ "type": "linear"
+ },
+ "show": true,
+ "style": {},
+ "title": {
+ "text": "Percentiles of AvgTicketPrice"
+ },
+ "type": "value"
+ }
+ ]
+ },
+ "data": {
+ "uiState": {},
+ "data": {
+ "xAxisOrderedValues": [
+ 1557460800000,
+ 1557547200000
+ ],
+ "xAxisFormat": {
+ "id": "date",
+ "params": {
+ "pattern": "YYYY-MM-DD"
+ }
+ },
+ "xAxisLabel": "timestamp per day",
+ "ordered": {
+ "interval": "P1D",
+ "date": true,
+ "min": 1557460800000,
+ "max": 1557656337342
+ },
+ "yAxisFormat": {
+ "id": "number",
+ "params": {
+ "pattern": "$0,0.[00]"
+ }
+ },
+ "yAxisLabel": "",
+ "hits": 2
+ },
+ "series": [
+ {
+ "id": "1.['1.1']",
+ "rawId": "col-1-1.['1.1']",
+ "label": "1.1th percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 116.33676605224609,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 1,
+ "row": 0,
+ "value": 116.33676605224609
+ },
+ "parent": null,
+ "series": "1.1th percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.['1.1']"
+ },
+ {
+ "x": 1557547200000,
+ "y": 223,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 1,
+ "row": 1,
+ "value": 223
+ },
+ "parent": null,
+ "series": "1.1th percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.['1.1']"
+ }
+ ]
+ },
+ {
+ "id": "1.50",
+ "rawId": "col-2-1.50",
+ "label": "50th percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 658.8453063964844,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 2,
+ "row": 0,
+ "value": 658
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ },
+ {
+ "x": 1557547200000,
+ "y": 756,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 2,
+ "row": 1,
+ "value": 756.2283554077148
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ }
+ ]
+ }
+ ],
+ "type": "series",
+ "labels": [
+ "1.1th percentile of AvgTicketPrice",
+ "50th percentile of AvgTicketPrice"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json
new file mode 100644
index 0000000000000..f7dd18f5eb712
--- /dev/null
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_float_value_result.json
@@ -0,0 +1,456 @@
+{
+ "addLegend": true,
+ "addTimeMarker": false,
+ "addTooltip": true,
+ "categoryAxes": [
+ {
+ "id": "CategoryAxis-1",
+ "labels": {
+ "show": true,
+ "truncate": 100
+ },
+ "position": "bottom",
+ "scale": {
+ "type": "linear"
+ },
+ "show": true,
+ "style": {},
+ "title": {
+ "text": "Date Histogram"
+ },
+ "type": "category"
+ }
+ ],
+ "dimensions": {
+ "x": {
+ "accessor": 0,
+ "format": {
+ "id": "date",
+ "params": {
+ "pattern": "YYYY-MM-DD"
+ }
+ },
+ "params": {
+ "date": true,
+ "interval": "P1D",
+ "format": "YYYY-MM-DD",
+ "bounds": {
+ "min": "2019-05-10T04:00:00.000Z",
+ "max": "2019-05-12T10:18:57.342Z"
+ }
+ },
+ "aggType": "date_histogram"
+ },
+ "y": [
+ {
+ "accessor": 1,
+ "format": {
+ "id": "number",
+ "params": {
+ "pattern": "$0,0.[00]"
+ }
+ },
+ "params": {},
+ "aggType": "percentiles"
+ },
+ {
+ "accessor": 2,
+ "format": {
+ "id": "number",
+ "params": {
+ "pattern": "$0,0.[00]"
+ }
+ },
+ "params": {},
+ "aggType": "percentiles"
+ }
+ ]
+ },
+ "grid": {
+ "categoryLines": false,
+ "style": {
+ "color": "#eee"
+ }
+ },
+ "legendPosition": "right",
+ "seriesParams": [
+ {
+ "data": {
+ "id": "1",
+ "label": "Percentiles of AvgTicketPrice"
+ },
+ "drawLinesBetweenPoints": true,
+ "interpolate": "cardinal",
+ "mode": "normal",
+ "show": "true",
+ "showCircles": true,
+ "type": "line",
+ "valueAxis": "ValueAxis-1"
+ }
+ ],
+ "times": [],
+ "type": "point_series",
+ "valueAxes": [
+ {
+ "id": "ValueAxis-1",
+ "labels": {
+ "filter": false,
+ "rotate": 0,
+ "show": true,
+ "truncate": 100
+ },
+ "name": "LeftAxis-1",
+ "position": "left",
+ "scale": {
+ "mode": "normal",
+ "type": "linear"
+ },
+ "show": true,
+ "style": {},
+ "title": {
+ "text": "Percentiles of AvgTicketPrice"
+ },
+ "type": "value"
+ }
+ ],
+ "chartTitle": {},
+ "mode": "normal",
+ "tooltip": {
+ "show": true
+ },
+ "charts": [
+ {
+ "type": "point_series",
+ "addTimeMarker": false,
+ "series": [
+ {
+ "show": true,
+ "type": "area",
+ "mode": "normal",
+ "drawLinesBetweenPoints": true,
+ "showCircles": true,
+ "data": {
+ "id": "1.['1.1']",
+ "rawId": "col-1-1.['1.1']",
+ "label": "1.1th percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 116.33676605224609,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 1,
+ "row": 0,
+ "value": 116.33676605224609
+ },
+ "parent": null,
+ "series": "1.1th percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.['1.1']"
+ },
+ {
+ "x": 1557547200000,
+ "y": 223,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 1,
+ "row": 1,
+ "value": 223
+ },
+ "parent": null,
+ "series": "1.1th percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.['1.1']"
+ }
+ ]
+ }
+ },
+ {
+ "data": {
+ "id": "1.50",
+ "rawId": "col-2-1.50",
+ "label": "50th percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 658.8453063964844,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 2,
+ "row": 0,
+ "value": 658
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ },
+ {
+ "x": 1557547200000,
+ "y": 756,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.['1.1']",
+ "name": "1.1th percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.['1.1']": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.['1.1']": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 2,
+ "row": 1,
+ "value": 756.2283554077148
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ }
+ ]
+ },
+ "drawLinesBetweenPoints": true,
+ "interpolate": "cardinal",
+ "mode": "normal",
+ "show": "true",
+ "showCircles": true,
+ "type": "line",
+ "valueAxis": "ValueAxis-1"
+ }
+ ]
+ }
+ ],
+ "enableHover": true
+}
\ No newline at end of file
diff --git a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json
index d50d20a70608b..02062c987564e 100644
--- a/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json
+++ b/src/plugins/vis_type_vislib/public/vislib/lib/types/testdata_linechart_percentile_result.json
@@ -122,8 +122,337 @@
{
"type": "point_series",
"addTimeMarker": false,
- "series": []
+ "series": [
+ {
+ "data": {
+ "id": "1.1",
+ "rawId": "col-1-1.1",
+ "label": "1st percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 116.33676605224609,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 1,
+ "row": 0,
+ "value": 116.33676605224609
+ },
+ "parent": null,
+ "series": "1st percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.1"
+ },
+ {
+ "x": 1557547200000,
+ "y": 223,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 1,
+ "row": 1,
+ "value": 223
+ },
+ "parent": null,
+ "series": "1st percentile of AvgTicketPrice",
+ "seriesId": "col-1-1.1"
+ }
+ ]
+ },
+ "drawLinesBetweenPoints": true,
+ "interpolate": "cardinal",
+ "mode": "normal",
+ "show": "true",
+ "showCircles": true,
+ "type": "line",
+ "valueAxis": "ValueAxis-1"
+ },
+ {
+ "data": {
+ "id": "1.50",
+ "rawId": "col-2-1.50",
+ "label": "50th percentile of AvgTicketPrice",
+ "values": [
+ {
+ "x": 1557460800000,
+ "y": 658.8453063964844,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 0,
+ "value": 1557460800000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 2,
+ "row": 0,
+ "value": 658
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ },
+ {
+ "x": 1557547200000,
+ "y": 756,
+ "extraMetrics": [],
+ "xRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 0,
+ "row": 1,
+ "value": 1557547200000
+ },
+ "yRaw": {
+ "table": {
+ "columns": [
+ {
+ "id": "col-0-2",
+ "name": "timestamp per day"
+ },
+ {
+ "id": "col-1-1.1",
+ "name": "1st percentile of AvgTicketPrice"
+ },
+ {
+ "id": "col-2-1.50",
+ "name": "50th percentile of AvgTicketPrice"
+ }
+ ],
+ "rows": [
+ {
+ "col-0-2": 1557460800000,
+ "col-1-1.1": 116,
+ "col-2-1.50": 658
+ },
+ {
+ "col-0-2": 1557547200000,
+ "col-1-1.1": 223,
+ "col-2-1.50": 756
+ }
+ ]
+ },
+ "column": 2,
+ "row": 1,
+ "value": 756.2283554077148
+ },
+ "parent": null,
+ "series": "50th percentile of AvgTicketPrice",
+ "seriesId": "col-2-1.50"
+ }
+ ]
+ },
+ "drawLinesBetweenPoints": true,
+ "interpolate": "cardinal",
+ "mode": "normal",
+ "show": "true",
+ "showCircles": true,
+ "type": "line",
+ "valueAxis": "ValueAxis-1"
+ }
+ ]
}
],
"enableHover": true
-}
+}
\ No newline at end of file
diff --git a/src/plugins/visualizations/server/saved_objects/visualization.ts b/src/plugins/visualizations/server/saved_objects/visualization.ts
index c4756de0a8386..ad7618a8640ba 100644
--- a/src/plugins/visualizations/server/saved_objects/visualization.ts
+++ b/src/plugins/visualizations/server/saved_objects/visualization.ts
@@ -44,12 +44,14 @@ export const visualizationSavedObjectType: SavedObjectsType = {
mappings: {
properties: {
description: { type: 'text' },
- kibanaSavedObjectMeta: { properties: { searchSourceJSON: { type: 'text' } } },
- savedSearchRefName: { type: 'keyword' },
+ kibanaSavedObjectMeta: {
+ properties: { searchSourceJSON: { type: 'text', index: false, doc_values: false } },
+ },
+ savedSearchRefName: { type: 'keyword', index: false, doc_values: false },
title: { type: 'text' },
- uiStateJSON: { type: 'text' },
+ uiStateJSON: { type: 'text', index: false, doc_values: false },
version: { type: 'integer' },
- visState: { type: 'text' },
+ visState: { type: 'text', index: false, doc_values: false },
},
},
migrations: visualizationSavedObjectTypeMigrations,
diff --git a/tasks/config/karma.js b/tasks/config/karma.js
index fa4bdc8ed2266..114e09876406c 100644
--- a/tasks/config/karma.js
+++ b/tasks/config/karma.js
@@ -21,7 +21,6 @@ import { dirname } from 'path';
import { times } from 'lodash';
import { makeJunitReportPath } from '@kbn/test';
import * as UiSharedDeps from '@kbn/ui-shared-deps';
-import { DllCompiler } from '../../src/optimize/dynamic_dll_plugin';
const TOTAL_CI_SHARDS = 4;
const ROOT = dirname(require.resolve('../../package.json'));
@@ -63,12 +62,6 @@ module.exports = function (grunt) {
),
`http://localhost:5610/${buildHash}/bundles/kbn-ui-shared-deps/${UiSharedDeps.jsFilename}`,
- `http://localhost:5610/${buildHash}/built_assets/dlls/vendors_runtime.bundle.dll.js`,
- ...DllCompiler.getRawDllConfig().chunks.map(
- (chunk) =>
- `http://localhost:5610/${buildHash}/built_assets/dlls/vendors${chunk}.bundle.dll.js`
- ),
-
shardNum === undefined
? `http://localhost:5610/${buildHash}/bundles/tests.bundle.js`
: `http://localhost:5610/${buildHash}/bundles/tests.bundle.js?shards=${TOTAL_CI_SHARDS}&shard_num=${shardNum}`,
@@ -77,10 +70,6 @@ module.exports = function (grunt) {
// this causes tilemap tests to fail, probably because the eui styles haven't been
// included in the karma harness a long some time, if ever
// `http://localhost:5610/bundles/kbn-ui-shared-deps/${UiSharedDeps.lightCssDistFilename}`,
- ...DllCompiler.getRawDllConfig().chunks.map(
- (chunk) =>
- `http://localhost:5610/${buildHash}/built_assets/dlls/vendors${chunk}.style.dll.css`
- ),
`http://localhost:5610/${buildHash}/bundles/tests.style.css`,
];
}
@@ -133,7 +122,6 @@ module.exports = function (grunt) {
'/tests/': 'http://localhost:5610/tests/',
'/test_bundle/': 'http://localhost:5610/test_bundle/',
[`/${buildHash}/bundles/`]: `http://localhost:5610/${buildHash}/bundles/`,
- [`/${buildHash}/built_assets/dlls/`]: `http://localhost:5610/${buildHash}/built_assets/dlls/`,
},
client: {
diff --git a/test/functional/apps/dashboard/embeddable_rendering.js b/test/functional/apps/dashboard/embeddable_rendering.js
index 9ba0c07c744fc..c00f01d060f4a 100644
--- a/test/functional/apps/dashboard/embeddable_rendering.js
+++ b/test/functional/apps/dashboard/embeddable_rendering.js
@@ -98,8 +98,7 @@ export default function ({ getService, getPageObjects }) {
await dashboardExpect.vegaTextsDoNotExist(['5,000']);
};
- // FLAKY: https://github.com/elastic/kibana/issues/46305
- describe.skip('dashboard embeddable rendering', function describeIndexTests() {
+ describe('dashboard embeddable rendering', function describeIndexTests() {
before(async () => {
await esArchiver.load('dashboard/current/kibana');
await kibanaServer.uiSettings.replace({
diff --git a/x-pack/package.json b/x-pack/package.json
index 6715fa132c1b5..1de009ae1232f 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -72,6 +72,7 @@
"@types/graphql": "^0.13.2",
"@types/gulp": "^4.0.6",
"@types/hapi__wreck": "^15.0.1",
+ "@types/he": "^1.1.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/history": "^4.7.3",
"@types/jest": "^25.2.3",
@@ -265,6 +266,7 @@
"graphql-tools": "^3.0.2",
"h2o2": "^8.1.2",
"handlebars": "4.7.6",
+ "he": "^1.2.0",
"history": "4.9.0",
"history-extra": "^5.0.1",
"i18n-iso-countries": "^4.3.1",
diff --git a/x-pack/plugins/apm/scripts/package.json b/x-pack/plugins/apm/scripts/package.json
index c5a9df792f856..4d0906514b5e1 100644
--- a/x-pack/plugins/apm/scripts/package.json
+++ b/x-pack/plugins/apm/scripts/package.json
@@ -4,7 +4,7 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
- "@elastic/elasticsearch": "^7.6.1",
+ "@elastic/elasticsearch": "7.9.0-rc.1",
"@octokit/rest": "^16.35.0",
"@types/console-stamp": "^0.2.32",
"console-stamp": "^0.2.9",
diff --git a/x-pack/plugins/embeddable_enhanced/README.asciidoc b/x-pack/plugins/embeddable_enhanced/README.asciidoc
new file mode 100644
index 0000000000000..9a7fe9c2669d9
--- /dev/null
+++ b/x-pack/plugins/embeddable_enhanced/README.asciidoc
@@ -0,0 +1,6 @@
+[[enhanced-embeddables-plugin]]
+== Enhanced embeddables plugin
+
+Enhances Embeddables by registering a custom factory provider. The enhanced factory provider
+adds dynamic actions to every embeddables state, in order to support drilldowns.
+
diff --git a/x-pack/plugins/embeddable_enhanced/README.md b/x-pack/plugins/embeddable_enhanced/README.md
deleted file mode 100644
index a0be90731fdb0..0000000000000
--- a/x-pack/plugins/embeddable_enhanced/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# X-Pack part of `embeddable` plugin
diff --git a/x-pack/plugins/graph/server/lib/license_state.ts b/x-pack/plugins/graph/server/lib/license_state.ts
index d86cb5380a2e1..8d64c826d8fa1 100644
--- a/x-pack/plugins/graph/server/lib/license_state.ts
+++ b/x-pack/plugins/graph/server/lib/license_state.ts
@@ -7,6 +7,7 @@
import Boom from 'boom';
import { map } from 'rxjs/operators';
import { Observable, Subscription } from 'rxjs';
+import { LicensingPluginStart } from '../../../licensing/server';
import { ILicense } from '../../../licensing/common/types';
import { checkLicense, GraphLicenseInformation } from '../../common/check_license';
@@ -14,6 +15,7 @@ export class LicenseState {
private licenseInformation: GraphLicenseInformation = checkLicense(undefined);
private subscription: Subscription | null = null;
private observable: Observable | null = null;
+ private _notifyUsage: LicensingPluginStart['featureUsage']['notifyUsage'] | null = null;
private updateInformation(licenseInformation: GraphLicenseInformation) {
this.licenseInformation = licenseInformation;
@@ -24,6 +26,17 @@ export class LicenseState {
this.subscription = this.observable.subscribe(this.updateInformation.bind(this));
}
+ public setNotifyUsage(notifyUsage: LicensingPluginStart['featureUsage']['notifyUsage']) {
+ this._notifyUsage = notifyUsage;
+ }
+
+ // 'Graph' is the only allowed feature here at the moment, if this gets extended in the future, add to the union type
+ public notifyUsage(featureName: 'Graph') {
+ if (this._notifyUsage) {
+ this._notifyUsage(featureName);
+ }
+ }
+
public stop() {
if (this.subscription) {
this.subscription.unsubscribe();
diff --git a/x-pack/plugins/graph/server/plugin.ts b/x-pack/plugins/graph/server/plugin.ts
index 141d5d0ea8db4..b2b825fa4683b 100644
--- a/x-pack/plugins/graph/server/plugin.ts
+++ b/x-pack/plugins/graph/server/plugin.ts
@@ -5,8 +5,8 @@
*/
import { i18n } from '@kbn/i18n';
-import { Plugin, CoreSetup } from 'src/core/server';
-import { LicensingPluginSetup } from '../../licensing/server';
+import { Plugin, CoreSetup, CoreStart } from 'src/core/server';
+import { LicensingPluginSetup, LicensingPluginStart } from '../../licensing/server';
import { LicenseState } from './lib/license_state';
import { registerSearchRoute } from './routes/search';
import { registerExploreRoute } from './routes/explore';
@@ -34,6 +34,7 @@ export class GraphPlugin implements Plugin {
licenseState.start(licensing.license$);
this.licenseState = licenseState;
core.savedObjects.registerType(graphWorkspace);
+ licensing.featureUsage.register('Graph', 'platinum');
if (home) {
registerSampleData(home.sampleData, licenseState);
@@ -79,7 +80,10 @@ export class GraphPlugin implements Plugin {
registerExploreRoute({ licenseState, router });
}
- public start() {}
+ public start(core: CoreStart, { licensing }: { licensing: LicensingPluginStart }) {
+ this.licenseState!.setNotifyUsage(licensing.featureUsage.notifyUsage);
+ }
+
public stop() {
if (this.licenseState) {
this.licenseState.stop();
diff --git a/x-pack/plugins/graph/server/routes/explore.ts b/x-pack/plugins/graph/server/routes/explore.ts
index b0b8cf14ff699..c436fbd1c79af 100644
--- a/x-pack/plugins/graph/server/routes/explore.ts
+++ b/x-pack/plugins/graph/server/routes/explore.ts
@@ -42,6 +42,7 @@ export function registerExploreRoute({
response
) => {
verifyApiAccess(licenseState);
+ licenseState.notifyUsage('Graph');
try {
return response.ok({
body: {
diff --git a/x-pack/plugins/graph/server/routes/search.ts b/x-pack/plugins/graph/server/routes/search.ts
index 645e6b520013f..e1d430eeb311a 100644
--- a/x-pack/plugins/graph/server/routes/search.ts
+++ b/x-pack/plugins/graph/server/routes/search.ts
@@ -42,6 +42,7 @@ export function registerSearchRoute({
response
) => {
verifyApiAccess(licenseState);
+ licenseState.notifyUsage('Graph');
const includeFrozen = await uiSettings.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN);
try {
return response.ok({
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/setup_environment.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/setup_environment.ts
index b3205a9523c62..325d8193de5fd 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/setup_environment.ts
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/setup_environment.ts
@@ -29,6 +29,8 @@ export const setupEnvironment = () => {
);
mockHttpClient.interceptors.response.use(({ data }) => data);
+ // This expects HttpSetup but we're giving it AxiosInstance.
+ // @ts-ignore
initHttp(mockHttpClient);
const { server, httpRequestsMockHelpers } = initHttpRequests();
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts
index 065fb3bcebca7..30c341baa6194 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/api.ts
@@ -5,7 +5,6 @@
*/
import { METRIC_TYPE } from '@kbn/analytics';
-import { trackUiMetric } from './ui_metric';
import {
UIM_POLICY_DELETE,
@@ -15,8 +14,13 @@ import {
UIM_INDEX_RETRY_STEP,
} from '../constants';
+import { trackUiMetric } from './ui_metric';
import { sendGet, sendPost, sendDelete, useRequest } from './http';
+interface GenericObject {
+ [key: string]: any;
+}
+
export async function loadNodes() {
return await sendGet(`nodes/list`);
}
@@ -33,7 +37,7 @@ export async function loadPolicies(withIndices: boolean) {
return await sendGet('policies', { withIndices });
}
-export async function savePolicy(policy: any) {
+export async function savePolicy(policy: GenericObject) {
return await sendPost(`policies`, policy);
}
@@ -58,14 +62,14 @@ export const removeLifecycleForIndex = async (indexNames: string[]) => {
return response;
};
-export const addLifecyclePolicyToIndex = async (body: any) => {
+export const addLifecyclePolicyToIndex = async (body: GenericObject) => {
const response = await sendPost(`index/add`, body);
// Only track successful actions.
trackUiMetric(METRIC_TYPE.COUNT, UIM_POLICY_ATTACH_INDEX);
return response;
};
-export const addLifecyclePolicyToTemplate = async (body: any) => {
+export const addLifecyclePolicyToTemplate = async (body: GenericObject) => {
const response = await sendPost(`template`, body);
// Only track successful actions.
trackUiMetric(METRIC_TYPE.COUNT, UIM_POLICY_ATTACH_INDEX_TEMPLATE);
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.js b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts
similarity index 73%
rename from x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.js
rename to x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts
index af107b5cff4b1..7b8d48acced33 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.js
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts
@@ -4,10 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { IHttpFetchError } from 'src/core/public';
import { fatalErrors, toasts } from './notification';
-function createToastConfig(error, errorTitle) {
+function createToastConfig(error: IHttpFetchError, errorTitle: string) {
if (error && error.body) {
+ // Error body shape is defined by the API.
const { error: errorString, statusCode, message } = error.body;
return {
@@ -17,7 +19,7 @@ function createToastConfig(error, errorTitle) {
}
}
-export function showApiWarning(error, errorTitle) {
+export function showApiWarning(error: IHttpFetchError, errorTitle: string) {
const toastConfig = createToastConfig(error, errorTitle);
if (toastConfig) {
@@ -26,10 +28,10 @@ export function showApiWarning(error, errorTitle) {
// This error isn't an HTTP error, so let the fatal error screen tell the user something
// unexpected happened.
- return fatalErrors(error, errorTitle);
+ return fatalErrors.add(error, errorTitle);
}
-export function showApiError(error, errorTitle) {
+export function showApiError(error: IHttpFetchError, errorTitle: string) {
const toastConfig = createToastConfig(error, errorTitle);
if (toastConfig) {
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts
index c54ee15fd69bf..0b5f39a52c13f 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts
@@ -4,15 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { HttpSetup } from 'src/core/public';
import {
UseRequestConfig,
useRequest as _useRequest,
Error,
} from '../../../../../../src/plugins/es_ui_shared/public';
-let _httpClient: any;
+interface GenericObject {
+ [key: string]: any;
+}
+
+let _httpClient: HttpSetup;
-export function init(httpClient: any): void {
+export function init(httpClient: HttpSetup): void {
_httpClient = httpClient;
}
@@ -26,15 +31,15 @@ function getFullPath(path: string): string {
return apiPrefix;
}
-export function sendPost(path: string, payload: any): any {
+export function sendPost(path: string, payload: GenericObject) {
return _httpClient.post(getFullPath(path), { body: JSON.stringify(payload) });
}
-export function sendGet(path: string, query?: any): any {
+export function sendGet(path: string, query?: GenericObject): any {
return _httpClient.get(getFullPath(path), { query });
}
-export function sendDelete(path: string): any {
+export function sendDelete(path: string) {
return _httpClient.delete(getFullPath(path));
}
diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.tsx
similarity index 95%
rename from x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.js
rename to x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.tsx
index 048ed44bd58b2..6057522885b1d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.js
+++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.tsx
@@ -13,16 +13,13 @@ import { removeLifecycleForIndex } from '../../application/services/api';
import { showApiError } from '../../application/services/api_errors';
import { toasts } from '../../application/services/notification';
-export class RemoveLifecyclePolicyConfirmModal extends Component {
- constructor(props) {
- super(props);
- this.state = {
- policies: [],
- selectedPolicyName: null,
- selectedAlias: null,
- };
- }
+interface Props {
+ indexNames: string[];
+ closeModal: () => void;
+ reloadIndices: () => void;
+}
+export class RemoveLifecyclePolicyConfirmModal extends Component {
removePolicy = async () => {
const { indexNames, closeModal, reloadIndices } = this.props;
diff --git a/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx b/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx
index 0e0e23ef73a3a..f3136ca155c78 100644
--- a/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx
+++ b/x-pack/plugins/infra/public/alerting/common/components/alert_preview.tsx
@@ -14,13 +14,9 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiCallOut,
- EuiOverlayMask,
- EuiModal,
- EuiModalHeader,
- EuiModalHeaderTitle,
- EuiModalBody,
+ EuiAccordion,
EuiCodeBlock,
- EuiLink,
+ EuiText,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
@@ -61,9 +57,6 @@ export const AlertPreview: React.FC = (props) => {
const [previewResult, setPreviewResult] = useState<
(AlertPreviewSuccessResponsePayload & Record) | null
>(null);
- const [isErrorModalVisible, setIsErrorModalVisible] = useState(false);
- const onOpenModal = useCallback(() => setIsErrorModalVisible(true), [setIsErrorModalVisible]);
- const onCloseModal = useCallback(() => setIsErrorModalVisible(false), [setIsErrorModalVisible]);
const onSelectPreviewLookbackInterval = useCallback((e) => {
setPreviewLookbackInterval(e.target.value);
@@ -271,33 +264,32 @@ export const AlertPreview: React.FC = (props) => {
iconType="alert"
>
{previewError.body && (
- view the error,
- }}
- />
+ <>
+
+
+
+
+
+
+ >
+ }
+ >
+
+ {previewError.body.message}
+
+ >
)}
)}
- {isErrorModalVisible && (
-
-
-
-
-
-
-
-
- {previewError.body.message}
-
-
-
- )}
>
)}
>
diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx
index 21c7f48eb80f8..908e52f01cbcc 100644
--- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx
+++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useMemo, useState, useCallback, useContext } from 'react';
+import React, { useState, useCallback, useContext } from 'react';
import { i18n } from '@kbn/i18n';
import { encode } from 'rison-node';
import moment from 'moment';
@@ -40,12 +40,8 @@ export const CategoryExampleMessage: React.FunctionComponent<{
context: LogEntryContext;
}> = ({ id, dataset, message, timestamp, timeRange, tiebreaker, context }) => {
const [, { setContextEntry }] = useContext(ViewLogInContext.Context);
- // the dataset must be encoded for the field column and the empty value must
- // be turned into a user-friendly value
- const encodedDatasetFieldValue = useMemo(
- () => JSON.stringify(getFriendlyNameForPartitionId(dataset)),
- [dataset]
- );
+ // handle special cases for the dataset value
+ const humanFriendlyDataset = getFriendlyNameForPartitionId(dataset);
const [isHovered, setIsHovered] = useState(false);
const setHovered = useCallback(() => setIsHovered(true), []);
@@ -100,7 +96,7 @@ export const CategoryExampleMessage: React.FunctionComponent<{
columnValue={{
columnId: datasetColumnId,
field: 'event.dataset',
- value: encodedDatasetFieldValue,
+ value: humanFriendlyDataset,
highlights: [],
}}
highlights={noHighlights}
diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx
index 2965e1fede822..fece2522de574 100644
--- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx
+++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx
@@ -80,12 +80,8 @@ export const LogEntryExampleMessage: React.FunctionComponent = ({
const setItemIsHovered = useCallback(() => setIsHovered(true), []);
const setItemIsNotHovered = useCallback(() => setIsHovered(false), []);
- // the dataset must be encoded for the field column and the empty value must
- // be turned into a user-friendly value
- const encodedDatasetFieldValue = useMemo(
- () => JSON.stringify(getFriendlyNameForPartitionId(dataset)),
- [dataset]
- );
+ // handle special cases for the dataset value
+ const humanFriendlyDataset = getFriendlyNameForPartitionId(dataset);
const viewInStreamLinkProps = useLinkProps({
app: 'logs',
@@ -158,7 +154,7 @@ export const LogEntryExampleMessage: React.FunctionComponent = ({
columnValue={{
columnId: datasetColumnId,
field: 'event.dataset',
- value: encodedDatasetFieldValue,
+ value: humanFriendlyDataset,
highlights: [],
}}
highlights={noHighlights}
diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts
index fbbb38da53929..ab55601f4c475 100644
--- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts
+++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_alert_type.ts
@@ -56,6 +56,8 @@ const criteriaSchema = schema.object({
schema.literal(Comparator.NOT_EQ),
schema.literal(Comparator.MATCH),
schema.literal(Comparator.NOT_MATCH),
+ schema.literal(Comparator.MATCH_PHRASE),
+ schema.literal(Comparator.NOT_MATCH_PHRASE),
]),
value: schema.oneOf([schema.number(), schema.string()]),
});
diff --git a/x-pack/plugins/ingest_manager/common/mocks.ts b/x-pack/plugins/ingest_manager/common/mocks.ts
index e85364f2bb672..236324b11c580 100644
--- a/x-pack/plugins/ingest_manager/common/mocks.ts
+++ b/x-pack/plugins/ingest_manager/common/mocks.ts
@@ -44,3 +44,90 @@ export const createPackageConfigMock = (): PackageConfig => {
],
};
};
+
+export const createPackageConfigWithInitialManifestMock = (): PackageConfig => {
+ const packageConfig = createPackageConfigMock();
+ packageConfig.inputs[0].config!.artifact_manifest = {
+ value: {
+ artifacts: {
+ 'endpoint-exceptionlist-linux-v1': {
+ compression_algorithm: 'zlib',
+ encryption_algorithm: 'none',
+ decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ decoded_size: 14,
+ encoded_size: 22,
+ relative_url:
+ '/api/endpoint/artifacts/download/endpoint-exceptionlist-linux-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-exceptionlist-macos-v1': {
+ compression_algorithm: 'zlib',
+ encryption_algorithm: 'none',
+ decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ decoded_size: 14,
+ encoded_size: 22,
+ relative_url:
+ '/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-exceptionlist-windows-v1': {
+ compression_algorithm: 'zlib',
+ encryption_algorithm: 'none',
+ decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ decoded_size: 14,
+ encoded_size: 22,
+ relative_url:
+ '/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ },
+ manifest_version: 'a9b7ef358a363f327f479e31efc4f228b2277a7fb4d1914ca9b4e7ca9ffcf537',
+ schema_version: 'v1',
+ },
+ };
+ return packageConfig;
+};
+
+export const createPackageConfigWithManifestMock = (): PackageConfig => {
+ const packageConfig = createPackageConfigMock();
+ packageConfig.inputs[0].config!.artifact_manifest = {
+ value: {
+ artifacts: {
+ 'endpoint-exceptionlist-linux-v1': {
+ compression_algorithm: 'zlib',
+ encryption_algorithm: 'none',
+ decoded_sha256: '0a5a2013a79f9e60682472284a1be45ab1ff68b9b43426d00d665016612c15c8',
+ encoded_sha256: '57941169bb2c5416f9bd7224776c8462cb9a2be0fe8b87e6213e77a1d29be824',
+ decoded_size: 292,
+ encoded_size: 131,
+ relative_url:
+ '/api/endpoint/artifacts/download/endpoint-exceptionlist-linux-v1/0a5a2013a79f9e60682472284a1be45ab1ff68b9b43426d00d665016612c15c8',
+ },
+ 'endpoint-exceptionlist-macos-v1': {
+ compression_algorithm: 'zlib',
+ encryption_algorithm: 'none',
+ decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
+ encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
+ decoded_size: 432,
+ encoded_size: 147,
+ relative_url:
+ '/api/endpoint/artifacts/download/endpoint-exceptionlist-macos-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
+ },
+ 'endpoint-exceptionlist-windows-v1': {
+ compression_algorithm: 'zlib',
+ encryption_algorithm: 'none',
+ decoded_sha256: '96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
+ encoded_sha256: '975382ab55d019cbab0bbac207a54e2a7d489fad6e8f6de34fc6402e5ef37b1e',
+ decoded_size: 432,
+ encoded_size: 147,
+ relative_url:
+ '/api/endpoint/artifacts/download/endpoint-exceptionlist-windows-v1/96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3',
+ },
+ },
+ manifest_version: '520f6cf88b3f36a065c6ca81058d5f8690aadadf6fe857f8dec4cc37589e7283',
+ schema_version: 'v1',
+ },
+ };
+
+ return packageConfig;
+};
diff --git a/x-pack/plugins/ingest_manager/common/services/agent_status.ts b/x-pack/plugins/ingest_manager/common/services/agent_status.ts
index 6489c30308771..536003b0f743d 100644
--- a/x-pack/plugins/ingest_manager/common/services/agent_status.ts
+++ b/x-pack/plugins/ingest_manager/common/services/agent_status.ts
@@ -4,11 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- AGENT_POLLING_THRESHOLD_MS,
- AGENT_TYPE_PERMANENT,
- AGENT_SAVED_OBJECT_TYPE,
-} from '../constants';
+import { AGENT_POLLING_THRESHOLD_MS, AGENT_SAVED_OBJECT_TYPE } from '../constants';
import { Agent, AgentStatus } from '../types';
export function getAgentStatus(agent: Agent, now: number = Date.now()): AgentStatus {
@@ -41,8 +37,16 @@ export function getAgentStatus(agent: Agent, now: number = Date.now()): AgentSta
return 'online';
}
+export function buildKueryForEnrollingAgents() {
+ return `not ${AGENT_SAVED_OBJECT_TYPE}.last_checkin:*`;
+}
+
+export function buildKueryForUnenrollingAgents() {
+ return `${AGENT_SAVED_OBJECT_TYPE}.unenrollment_started_at:*`;
+}
+
export function buildKueryForOnlineAgents() {
- return `not (${buildKueryForOfflineAgents()}) AND not (${buildKueryForErrorAgents()})`;
+ return `not (${buildKueryForOfflineAgents()}) AND not (${buildKueryForErrorAgents()}) AND not (${buildKueryForEnrollingAgents()}) AND not (${buildKueryForUnenrollingAgents()})`;
}
export function buildKueryForErrorAgents() {
@@ -50,7 +54,7 @@ export function buildKueryForErrorAgents() {
}
export function buildKueryForOfflineAgents() {
- return `((${AGENT_SAVED_OBJECT_TYPE}.type:${AGENT_TYPE_PERMANENT} AND ${AGENT_SAVED_OBJECT_TYPE}.last_checkin < now-${
+ return `${AGENT_SAVED_OBJECT_TYPE}.last_checkin < now-${
(4 * AGENT_POLLING_THRESHOLD_MS) / 1000
- }s) AND not ( ${buildKueryForErrorAgents()} ))`;
+ }s AND not (${buildKueryForErrorAgents()})`;
}
diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts
index ed7d73ab0b719..7ec5a8d68311f 100644
--- a/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts
+++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/agent.ts
@@ -173,5 +173,6 @@ export interface GetAgentStatusResponse {
online: number;
error: number;
offline: number;
+ other: number;
};
}
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx
index 24b4baeaa092b..b8fab92e40da8 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx
@@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
+import React, { Fragment } from 'react';
import {
EuiFacetButton,
EuiFacetGroup,
@@ -14,8 +14,8 @@ import {
EuiTextColor,
EuiTitle,
} from '@elastic/eui';
-import React, { Fragment } from 'react';
import styled from 'styled-components';
+import { FormattedMessage } from '@kbn/i18n/react';
import {
AssetsGroupedByServiceByType,
AssetTypeToParts,
@@ -43,8 +43,15 @@ const FacetGroup = styled(EuiFacetGroup)`
`;
const FacetButton = styled(EuiFacetButton)`
- padding: '${(props) => props.theme.eui.paddingSizes.xs} 0';
- height: 'unset';
+ &&& {
+ .euiFacetButton__icon,
+ .euiFacetButton__quantity {
+ opacity: 1;
+ }
+ .euiFacetButton__text {
+ color: ${(props) => props.theme.eui.euiTextColor};
+ }
+ }
`;
export function AssetsFacetGroup({ assets }: { assets: AssetsGroupedByServiceByType }) {
@@ -70,7 +77,15 @@ export function AssetsFacetGroup({ assets }: { assets: AssetsGroupedByServiceByT
- {ServiceTitleMap[service]} Assets
+
+
+
@@ -83,13 +98,7 @@ export function AssetsFacetGroup({ assets }: { assets: AssetsGroupedByServiceByT
const iconType = type in AssetIcons && AssetIcons[type];
const iconNode = iconType ? : '';
return (
- {}}
- >
+
{AssetTitleMap[type]}
);
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/donut_chart.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/donut_chart.tsx
index bfa9c80f12851..99a4f27b428fe 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/donut_chart.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/donut_chart.tsx
@@ -31,7 +31,7 @@ export const DonutChart = ({ height, width, data }: DonutChartProps) => {
.ordinal()
// @ts-ignore
.domain(data)
- .range(['#017D73', '#98A2B3', '#BD271E']);
+ .range(['#017D73', '#98A2B3', '#BD271E', '#F5A700']);
const pieGenerator = d3.layout
.pie()
.value(({ value }: any) => value)
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx
index 46190033d4d6b..16acda9dc4afd 100644
--- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx
+++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx
@@ -66,6 +66,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => {
online: agentStatus?.online || 0,
offline: agentStatus?.offline || 0,
error: agentStatus?.error || 0,
+ other: agentStatus?.other || 0,
}}
/>
diff --git a/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts
index 718aca89ea4fd..4e4653ec023ce 100644
--- a/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts
+++ b/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts
@@ -135,6 +135,7 @@ export const createAgentConfigHandler: RequestHandler<
newSysPackageConfig.namespace = agentConfig.namespace;
await packageConfigService.create(soClient, callCluster, newSysPackageConfig, {
user,
+ bumpConfigRevision: false,
});
}
diff --git a/x-pack/plugins/ingest_manager/server/services/agent_config.ts b/x-pack/plugins/ingest_manager/server/services/agent_config.ts
index c068b594318c1..0a9adc1f1c593 100644
--- a/x-pack/plugins/ingest_manager/server/services/agent_config.ts
+++ b/x-pack/plugins/ingest_manager/server/services/agent_config.ts
@@ -41,7 +41,8 @@ class AgentConfigService {
soClient: SavedObjectsClientContract,
id: string,
agentConfig: Partial,
- user?: AuthenticatedUser
+ user?: AuthenticatedUser,
+ options: { bumpRevision: boolean } = { bumpRevision: true }
): Promise {
const oldAgentConfig = await this.get(soClient, id, false);
@@ -60,7 +61,7 @@ class AgentConfigService {
await soClient.update(SAVED_OBJECT_TYPE, id, {
...agentConfig,
- revision: oldAgentConfig.revision + 1,
+ ...(options.bumpRevision ? { revision: oldAgentConfig.revision + 1 } : {}),
updated_at: new Date().toISOString(),
updated_by: user ? user.username : 'system',
});
@@ -265,7 +266,7 @@ class AgentConfigService {
soClient: SavedObjectsClientContract,
id: string,
packageConfigIds: string[],
- options?: { user?: AuthenticatedUser }
+ options: { user?: AuthenticatedUser; bumpRevision: boolean } = { bumpRevision: true }
): Promise {
const oldAgentConfig = await this.get(soClient, id, false);
@@ -281,7 +282,8 @@ class AgentConfigService {
[...((oldAgentConfig.package_configs || []) as string[])].concat(packageConfigIds)
),
},
- options?.user
+ options?.user,
+ { bumpRevision: options.bumpRevision }
);
}
diff --git a/x-pack/plugins/ingest_manager/server/services/agents/status.ts b/x-pack/plugins/ingest_manager/server/services/agents/status.ts
index 016a2344cf532..86336714a511e 100644
--- a/x-pack/plugins/ingest_manager/server/services/agents/status.ts
+++ b/x-pack/plugins/ingest_manager/server/services/agents/status.ts
@@ -25,9 +25,10 @@ export async function getAgentStatusForConfig(
soClient: SavedObjectsClientContract,
configId?: string
) {
- const [all, error, offline] = await Promise.all(
+ const [all, online, error, offline] = await Promise.all(
[
undefined,
+ AgentStatusKueryHelper.buildKueryForOnlineAgents(),
AgentStatusKueryHelper.buildKueryForErrorAgents(),
AgentStatusKueryHelper.buildKueryForOfflineAgents(),
].map((kuery) =>
@@ -47,9 +48,10 @@ export async function getAgentStatusForConfig(
return {
events: await getEventsCount(soClient, configId),
total: all.total,
- online: all.total - error.total - offline.total,
+ online: online.total,
error: error.total,
offline: offline.total,
+ other: all.total - online.total - error.total - offline.total,
};
}
diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap
index 219c2de675359..0333fb024a717 100644
--- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap
+++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap
@@ -87,6 +87,13 @@ exports[`tests loading base.yml: base.yml 1`] = `
"validarray": {
"type": "integer"
}
+ },
+ "_meta": {
+ "package": {
+ "name": "nginx"
+ },
+ "managed_by": "ingest-manager",
+ "managed": true
}
},
"aliases": {}
@@ -190,6 +197,13 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = `
}
}
}
+ },
+ "_meta": {
+ "package": {
+ "name": "coredns"
+ },
+ "managed_by": "ingest-manager",
+ "managed": true
}
},
"aliases": {}
@@ -1677,6 +1691,13 @@ exports[`tests loading system.yml: system.yml 1`] = `
}
}
}
+ },
+ "_meta": {
+ "package": {
+ "name": "system"
+ },
+ "managed_by": "ingest-manager",
+ "managed": true
}
},
"aliases": {}
diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts
index 876573f2270ea..a739806d5868b 100644
--- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts
+++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts
@@ -249,6 +249,15 @@ function getBaseTemplate(
packageName: string,
composedOfTemplates: string[]
): IndexTemplate {
+ // Meta information to identify Ingest Manager's managed templates and indices
+ const _meta = {
+ package: {
+ name: packageName,
+ },
+ managed_by: 'ingest-manager',
+ managed: true,
+ };
+
return {
// This takes precedence over all index templates installed by ES by default (logs-*-* and metrics-*-*)
// if this number is lower than the ES value (which is 100) this template will never be applied when a data stream
@@ -304,19 +313,14 @@ function getBaseTemplate(
date_detection: false,
// All the properties we know from the fields.yml file
properties: mappings.properties,
+ _meta,
},
// To be filled with the aliases that we need
aliases: {},
},
data_stream: {},
composed_of: composedOfTemplates,
- _meta: {
- package: {
- name: packageName,
- },
- managed_by: 'ingest-manager',
- managed: true,
- },
+ _meta,
};
}
diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts
index 2a743f244e64d..a3fe444b19b1a 100644
--- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts
+++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts
@@ -11,10 +11,14 @@ import {
} from 'src/core/server';
import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../../../common';
import * as Registry from '../../registry';
-import { AssetType, KibanaAssetType, AssetReference } from '../../../../types';
+import {
+ AssetType,
+ KibanaAssetType,
+ AssetReference,
+ KibanaAssetReference,
+} from '../../../../types';
import { deleteKibanaSavedObjectsAssets } from '../../packages/remove';
import { getInstallationObject, savedObjectTypes } from '../../packages';
-import { saveInstalledKibanaRefs } from '../../packages/install';
type SavedObjectToBe = Required & { type: AssetType };
export type ArchiveAsset = Pick<
@@ -49,7 +53,7 @@ export async function installKibanaAssets(options: {
pkgName: string;
paths: string[];
isUpdate: boolean;
-}): Promise {
+}): Promise {
const { savedObjectsClient, paths, pkgName, isUpdate } = options;
if (isUpdate) {
@@ -65,16 +69,14 @@ export async function installKibanaAssets(options: {
// install the new assets and save installation references
const kibanaAssetTypes = Object.values(KibanaAssetType);
- const installationPromises = kibanaAssetTypes.map((assetType) =>
- installKibanaSavedObjects({ savedObjectsClient, assetType, paths })
+ const installedAssets = await Promise.all(
+ kibanaAssetTypes.map((assetType) =>
+ installKibanaSavedObjects({ savedObjectsClient, assetType, paths })
+ )
);
// installKibanaSavedObjects returns AssetReference[], so .map creates AssetReference[][]
// call .flat to flatten into one dimensional array
- const newInstalledKibanaAssets = await Promise.all(installationPromises).then((results) =>
- results.flat()
- );
- await saveInstalledKibanaRefs(savedObjectsClient, pkgName, newInstalledKibanaAssets);
- return newInstalledKibanaAssets;
+ return installedAssets.flat();
}
export const deleteKibanaInstalledRefs = async (
savedObjectsClient: SavedObjectsClientContract,
diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts
index cd4259a0c30d7..a69daae6e0410 100644
--- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts
+++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts
@@ -169,17 +169,20 @@ export async function installPackage(options: {
);
}
- // update to newly installed version when all assets are successfully installed
- if (isUpdate) await updateVersion(savedObjectsClient, pkgName, pkgVersion);
// get template refs to save
const installedTemplateRefs = installedTemplates.map((template) => ({
id: template.templateName,
type: ElasticsearchAssetType.indexTemplate,
}));
+
const [installedKibanaAssets] = await Promise.all([
installKibanaAssetsPromise,
installIndexPatternPromise,
]);
+
+ await saveInstalledKibanaRefs(savedObjectsClient, pkgName, installedKibanaAssets);
+ // update to newly installed version when all assets are successfully installed
+ if (isUpdate) await updateVersion(savedObjectsClient, pkgName, pkgVersion);
return [...installedKibanaAssets, ...installedPipelines, ...installedTemplateRefs];
}
const updateVersion = async (
@@ -230,7 +233,7 @@ export async function createInstallation(options: {
export const saveInstalledKibanaRefs = async (
savedObjectsClient: SavedObjectsClientContract,
pkgName: string,
- installedAssets: AssetReference[]
+ installedAssets: KibanaAssetReference[]
) => {
await savedObjectsClient.update(PACKAGES_SAVED_OBJECT_TYPE, pkgName, {
installed_kibana: installedAssets,
diff --git a/x-pack/plugins/ingest_manager/server/services/package_config.ts b/x-pack/plugins/ingest_manager/server/services/package_config.ts
index e8ca09a83c2b6..c2d465cf7c73f 100644
--- a/x-pack/plugins/ingest_manager/server/services/package_config.ts
+++ b/x-pack/plugins/ingest_manager/server/services/package_config.ts
@@ -42,7 +42,7 @@ class PackageConfigService {
soClient: SavedObjectsClientContract,
callCluster: CallESAsCurrentUser,
packageConfig: NewPackageConfig,
- options?: { id?: string; user?: AuthenticatedUser }
+ options?: { id?: string; user?: AuthenticatedUser; bumpConfigRevision?: boolean }
): Promise {
// Check that its agent config does not have a package config with the same name
const parentAgentConfig = await agentConfigService.get(soClient, packageConfig.config_id);
@@ -104,6 +104,7 @@ class PackageConfigService {
// Assign it to the given agent config
await agentConfigService.assignPackageConfigs(soClient, packageConfig.config_id, [newSo.id], {
user: options?.user,
+ bumpRevision: options?.bumpConfigRevision ?? true,
});
return {
@@ -117,7 +118,7 @@ class PackageConfigService {
soClient: SavedObjectsClientContract,
packageConfigs: NewPackageConfig[],
configId: string,
- options?: { user?: AuthenticatedUser }
+ options?: { user?: AuthenticatedUser; bumpConfigRevision?: boolean }
): Promise {
const isoDate = new Date().toISOString();
const { saved_objects: newSos } = await soClient.bulkCreate(
@@ -142,6 +143,7 @@ class PackageConfigService {
newSos.map((newSo) => newSo.id),
{
user: options?.user,
+ bumpRevision: options?.bumpConfigRevision ?? true,
}
);
diff --git a/x-pack/plugins/ingest_manager/server/services/setup.ts b/x-pack/plugins/ingest_manager/server/services/setup.ts
index 627abc158143d..c91cae98e17d2 100644
--- a/x-pack/plugins/ingest_manager/server/services/setup.ts
+++ b/x-pack/plugins/ingest_manager/server/services/setup.ts
@@ -218,5 +218,7 @@ async function addPackageToConfig(
config.namespace
);
- await packageConfigService.create(soClient, callCluster, newPackageConfig);
+ await packageConfigService.create(soClient, callCluster, newPackageConfig, {
+ bumpConfigRevision: false,
+ });
}
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.test.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.test.tsx
index acfa012990b21..df4832f9a45e0 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.test.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/__jest__/pipeline_processors_editor.test.tsx
@@ -178,5 +178,13 @@ describe('Pipeline Editor', () => {
expect(data2.processors).toEqual(testProcessors.processors);
expect(data2.on_failure).toEqual([{ test: { if: '1 == 5' } }]);
});
+
+ it('prevents moving a processor while in edit mode', () => {
+ const { find, exists } = testBed;
+ find('processors>0.editItemButton').simulate('click');
+ expect(exists('processorSettingsForm')).toBe(true);
+ expect(find('processors>0.moveItemButton').props().disabled).toBe(true);
+ expect(find('processors>1.moveItemButton').props().disabled).toBe(true);
+ });
});
});
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/_shared.scss b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/_shared.scss
index c7c49c00bb5cf..fe9a54671a00e 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/_shared.scss
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/_shared.scss
@@ -1,2 +1,3 @@
$dropZoneZIndex: $euiZLevel1; /* Prevent the next item down from obscuring the button */
$cancelButtonZIndex: $euiZLevel2;
+$processorItemMouseTooltipZIndex: $euiZLevel3;
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/index.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/index.ts
index de0621b187230..b532b2d953e65 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/index.ts
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/index.ts
@@ -19,3 +19,5 @@ export { PipelineProcessorsEditorItem } from './pipeline_processors_editor_item'
export { ProcessorRemoveModal } from './processor_remove_modal';
export { OnDoneLoadJsonHandler, LoadFromJsonButton } from './load_from_json';
+
+export { PipelineProcessorsItemTooltip, Position } from './pipeline_processors_editor_item_tooltip';
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx
index 97b57a971ff7d..3fbef4c1b7898 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx
@@ -51,7 +51,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo(
editor,
processorsDispatch,
}) {
- const isDisabled = editor.mode.id !== 'idle';
+ const isEditorNotInIdleMode = editor.mode.id !== 'idle';
const isInMoveMode = Boolean(movingProcessor);
const isMovingThisProcessor = processor.id === movingProcessor?.id;
const isEditingThisProcessor =
@@ -83,6 +83,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo(
'pipelineProcessorsEditor__item__moveButton--cancel': isMovingThisProcessor,
});
const icon = isMovingThisProcessor ? 'cross' : 'sortable';
+ const disabled = isEditorNotInIdleMode && !isMovingThisProcessor;
const moveButton = (
= memo(
iconType={icon}
data-test-subj={dataTestSubj}
size="s"
- disabled={isDisabled && !isMovingThisProcessor}
+ isDisabled={disabled}
label={label}
aria-label={label}
- onChange={() => (!isMovingThisProcessor ? onMove() : onCancelMove())}
+ onChange={() => {
+ if (isMovingThisProcessor) {
+ onCancelMove();
+ } else {
+ onMove();
+ }
+ }}
/>
);
// Remove the tooltip from the DOM to prevent it from lingering if the mouse leave event
@@ -132,7 +139,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo(
{
let nextOptions: Record;
if (!nextDescription) {
@@ -164,7 +171,8 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo(
{!isInMoveMode && (
= memo(
{
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/index.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/index.ts
new file mode 100644
index 0000000000000..33692a8a4fd7c
--- /dev/null
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/index.ts
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { PipelineProcessorsItemTooltip, Position } from './pipeline_processors_editor_item_tooltip';
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/pipeline_processors_editor_item_toolip.scss b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/pipeline_processors_editor_item_toolip.scss
new file mode 100644
index 0000000000000..dd957ffeea65e
--- /dev/null
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/pipeline_processors_editor_item_toolip.scss
@@ -0,0 +1,7 @@
+@import '../shared';
+
+.pipelineProcessorsEditor__itemTooltip {
+ position: fixed;
+ pointer-events: none;
+ z-index: $processorItemMouseTooltipZIndex;
+}
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/pipeline_processors_editor_item_tooltip.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/pipeline_processors_editor_item_tooltip.tsx
new file mode 100644
index 0000000000000..ff1d9ed5466af
--- /dev/null
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/pipeline_processors_editor_item_tooltip.tsx
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { FunctionComponent, useEffect, useState } from 'react';
+import { EuiPortal } from '@elastic/eui';
+import { ProcessorInternal } from '../../types';
+
+import './pipeline_processors_editor_item_toolip.scss';
+import { ProcessorInformation } from './processor_information';
+
+export interface Position {
+ x: number;
+ y: number;
+}
+
+interface Props {
+ processor: ProcessorInternal;
+}
+
+const MOUSE_PADDING_RIGHT = 20;
+const MOUSE_PADDING_BOTTOM = 20;
+
+export const PipelineProcessorsItemTooltip: FunctionComponent = ({ processor }) => {
+ const [position, setPosition] = useState();
+
+ useEffect(() => {
+ const mouseMoveListener = (event: MouseEvent) => {
+ setPosition({ x: event.pageX, y: event.pageY - window.scrollY });
+ };
+ document.addEventListener('mousemove', mouseMoveListener);
+ return () => {
+ document.removeEventListener('mousemove', mouseMoveListener);
+ };
+ }, []);
+
+ if (!position) {
+ return null;
+ }
+
+ return (
+ /**
+ * To get around issues with parent elements potentially being position: relative or
+ * overflow: hidden we use a portal to render this tooltip in the document body so
+ * that we can render it anywhere the cursor can go.
+ */
+
+
+
+ );
+};
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/processor_information.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/processor_information.tsx
new file mode 100644
index 0000000000000..96abd7ebcd7ce
--- /dev/null
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/pipeline_processors_editor_item_tooltip/processor_information.tsx
@@ -0,0 +1,32 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { FunctionComponent, memo } from 'react';
+import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
+import { ProcessorInternal } from '../../types';
+
+interface Props {
+ processor: ProcessorInternal;
+}
+
+export const ProcessorInformation: FunctionComponent = memo(({ processor }) => {
+ return (
+
+
+
+ {processor.type}
+
+ {processor.options.description ? (
+
+
+ {processor.options.description}
+
+
+ ) : undefined}
+
+
+ );
+});
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/components/drop_zone_button.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/components/drop_zone_button.tsx
index 4cd734f8a819e..193b5b9afe447 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/components/drop_zone_button.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/components/drop_zone_button.tsx
@@ -37,7 +37,6 @@ export const DropZoneButton: FunctionComponent = (props) => {
});
const buttonClasses = classNames({
'pipelineProcessorsEditor__tree__dropZoneButton--visible': isVisible,
- 'pipelineProcessorsEditor__tree__dropZoneButton--unavailable': isUnavailable,
});
const content = (
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss
index 2feb71f21a4f5..061c9adb5d443 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/components/processors_tree/processors_tree.scss
@@ -50,10 +50,6 @@
transform: none !important;
}
}
-
- &--unavailable {
- cursor: not-allowed !important;
- }
}
&__onFailureHandlerContainer {
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/constants.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/constants.ts
index 87e6eb7f642a6..46e3d1c803fd5 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/constants.ts
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/constants.ts
@@ -4,12 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ON_FAILURE_STATE_SCOPE, PROCESSOR_STATE_SCOPE } from './processors_reducer';
-
export enum DropSpecialLocations {
top = 'TOP',
bottom = 'BOTTOM',
}
-
-export const PROCESSORS_BASE_SELECTOR = [PROCESSOR_STATE_SCOPE];
-export const ON_FAILURE_BASE_SELECTOR = [ON_FAILURE_STATE_SCOPE];
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/context.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/context.tsx
index 5b1f12418b4a2..098473b0d2572 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/context.tsx
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/context.tsx
@@ -25,6 +25,7 @@ import {
ContextValue,
ContextValueState,
Links,
+ ProcessorInternal,
} from './types';
import { useProcessorsState, isOnFailureSelector } from './processors_reducer';
@@ -33,11 +34,14 @@ import { deserialize } from './deserialize';
import { serialize } from './serialize';
-import { OnSubmitHandler, ProcessorSettingsForm } from './components/processor_settings_form';
-
import { OnActionHandler } from './components/processors_tree';
-import { ProcessorRemoveModal } from './components';
+import {
+ ProcessorRemoveModal,
+ PipelineProcessorsItemTooltip,
+ ProcessorSettingsForm,
+ OnSubmitHandler,
+} from './components';
import { getValue } from './utils';
@@ -64,6 +68,7 @@ export const PipelineProcessorsContextProvider: FunctionComponent = ({
children,
}) => {
const initRef = useRef(false);
+
const [mode, setMode] = useState(() => ({
id: 'idle',
}));
@@ -206,6 +211,15 @@ export const PipelineProcessorsContextProvider: FunctionComponent = ({
>
{children}
+ {mode.id === 'movingProcessor' && (
+ (mode.arg.selector, {
+ processors,
+ onFailure: onFailureProcessors,
+ })}
+ />
+ )}
+
{mode.id === 'editingProcessor' || mode.id === 'creatingProcessor' ? (
= ({
{mode.id === 'removingProcessor' && (
(mode.arg.selector, {
processors,
onFailure: onFailureProcessors,
})}
diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/types.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/types.ts
index aaca4108bb583..1ed54817b3aa9 100644
--- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/types.ts
+++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_processors_editor/types.ts
@@ -7,7 +7,7 @@
import { Dispatch } from 'react';
import { OnFormUpdateArg } from '../../../shared_imports';
import { SerializeResult } from './serialize';
-import { OnActionHandler, ProcessorInfo } from './components/processors_tree';
+import { OnActionHandler, ProcessorInfo } from './components';
import { ProcessorsDispatch, State as ProcessorsReducerState } from './processors_reducer';
export interface Links {
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx
index 7f4a48fa2fda2..73126b814f256 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx
@@ -129,7 +129,7 @@ function LayerPanels(
className="lnsConfigPanel__addLayerBtn"
fullWidth
size="s"
- data-test-subj="lnsXY_layer_add"
+ data-test-subj="lnsLayerAddButton"
aria-label={i18n.translate('xpack.lens.xyChart.addLayerButton', {
defaultMessage: 'Add layer',
})}
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx
index 1f987f86d3950..9545bd3c840da 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx
@@ -93,14 +93,14 @@ describe('LayerPanel', () => {
describe('layer reset and remove', () => {
it('should show the reset button when single layer', () => {
const component = mountWithIntl();
- expect(component.find('[data-test-subj="lns_layer_remove"]').first().text()).toContain(
+ expect(component.find('[data-test-subj="lnsLayerRemove"]').first().text()).toContain(
'Reset layer'
);
});
it('should show the delete button when multiple layers', () => {
const component = mountWithIntl();
- expect(component.find('[data-test-subj="lns_layer_remove"]').first().text()).toContain(
+ expect(component.find('[data-test-subj="lnsLayerRemove"]').first().text()).toContain(
'Delete layer'
);
});
@@ -109,7 +109,7 @@ describe('LayerPanel', () => {
const cb = jest.fn();
const component = mountWithIntl();
act(() => {
- component.find('[data-test-subj="lns_layer_remove"]').first().simulate('click');
+ component.find('[data-test-subj="lnsLayerRemove"]').first().simulate('click');
});
expect(cb).toHaveBeenCalled();
});
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx
index e51a155a19935..f72b1429967d2 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx
@@ -429,7 +429,7 @@ export function LayerPanel(
size="xs"
iconType="trash"
color="danger"
- data-test-subj="lns_layer_remove"
+ data-test-subj="lnsLayerRemove"
onClick={() => {
// If we don't blur the remove / clear button, it remains focused
// which is a strange UX in this case. e.target.blur doesn't work
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx
index 648bb5c03cb39..ceced2a7a353c 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx
@@ -46,6 +46,16 @@ describe('chart_switch', () => {
};
}
+ /**
+ * There are three visualizations. Each one has the same suggestion behavior:
+ *
+ * visA: suggests an empty state
+ * visB: suggests an empty state
+ * visC:
+ * - Never switches to subvisC2
+ * - Allows a switch to subvisC3
+ * - Allows a switch to subvisC1
+ */
function mockVisualizations() {
return {
visA: generateVisualization('visA'),
@@ -292,6 +302,49 @@ describe('chart_switch', () => {
expect(getMenuItem('visB', component).prop('betaBadgeIconType')).toEqual('alert');
});
+ it('should support multi-layer suggestions without data loss', () => {
+ const dispatch = jest.fn();
+ const visualizations = mockVisualizations();
+ const frame = mockFrame(['a', 'b']);
+
+ const datasourceMap = mockDatasourceMap();
+ datasourceMap.testDatasource.getDatasourceSuggestionsFromCurrentState.mockReturnValue([
+ {
+ state: {},
+ table: {
+ columns: [
+ {
+ columnId: 'a',
+ operation: {
+ label: '',
+ dataType: 'string',
+ isBucketed: true,
+ },
+ },
+ ],
+ isMultiRow: true,
+ layerId: 'a',
+ changeType: 'unchanged',
+ },
+ keptLayerIds: ['a', 'b'],
+ },
+ ]);
+
+ const component = mount(
+
+ );
+
+ expect(getMenuItem('visB', component).prop('betaBadgeIconType')).toBeUndefined();
+ });
+
it('should indicate data loss if no data will be used', () => {
const dispatch = jest.fn();
const visualizations = mockVisualizations();
diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx
index fa87d80e5cf40..51b4a347af6f1 100644
--- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx
+++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx
@@ -139,7 +139,7 @@ export function ChartSwitch(props: Props) {
dataLoss = 'nothing';
} else if (!topSuggestion) {
dataLoss = 'everything';
- } else if (layers.length > 1) {
+ } else if (layers.length > 1 && layers.length !== topSuggestion.keptLayerIds.length) {
dataLoss = 'layers';
} else if (topSuggestion.columns !== layers[0][1].getTableSpec().length) {
dataLoss = 'columns';
@@ -258,14 +258,15 @@ function getTopSuggestion(
newVisualization: Visualization,
subVisualizationId?: string
): Suggestion | undefined {
- const suggestions = getSuggestions({
+ const unfilteredSuggestions = getSuggestions({
datasourceMap: props.datasourceMap,
datasourceStates: props.datasourceStates,
visualizationMap: { [visualizationId]: newVisualization },
activeVisualizationId: props.visualizationId,
visualizationState: props.visualizationState,
subVisualizationId,
- }).filter((suggestion) => {
+ });
+ const suggestions = unfilteredSuggestions.filter((suggestion) => {
// don't use extended versions of current data table on switching between visualizations
// to avoid confusing the user.
return (
diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts
index f301206355060..f5828dbaeccc3 100644
--- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts
@@ -13,6 +13,7 @@ import {
} from '../types';
import { State, XYState, visualizationTypes } from './types';
import { generateId } from '../id_generator';
+import { xyVisualization } from './xy_visualization';
jest.mock('../id_generator');
@@ -119,7 +120,33 @@ describe('xy_suggestions', () => {
});
expect(suggestions).toHaveLength(visualizationTypes.length);
- expect(suggestions.map(({ state }) => state.preferredSeriesType)).toEqual([
+ expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([
+ 'bar_stacked',
+ 'area_stacked',
+ 'area',
+ 'line',
+ 'bar_horizontal_stacked',
+ 'bar_horizontal',
+ 'bar',
+ ]);
+ });
+
+ // This limitation is acceptable for now, but is now tested
+ test('is unable to generate layers when switching from a non-XY chart with multiple layers', () => {
+ (generateId as jest.Mock).mockReturnValueOnce('aaa');
+ const suggestions = getSuggestions({
+ table: {
+ isMultiRow: true,
+ columns: [numCol('bytes'), dateCol('date')],
+ layerId: 'first',
+ changeType: 'unchanged',
+ },
+ keptLayerIds: ['first', 'second'],
+ });
+
+ expect(suggestions).toHaveLength(visualizationTypes.length);
+ expect(suggestions.map(({ state }) => state.layers.length)).toEqual([1, 1, 1, 1, 1, 1, 1]);
+ expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([
'bar_stacked',
'area_stacked',
'area',
@@ -156,7 +183,51 @@ describe('xy_suggestions', () => {
});
expect(suggestions).toHaveLength(visualizationTypes.length);
- expect(suggestions.map(({ state }) => state.preferredSeriesType)).toEqual([
+ expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([
+ 'line',
+ 'bar',
+ 'bar_horizontal',
+ 'bar_stacked',
+ 'bar_horizontal_stacked',
+ 'area',
+ 'area_stacked',
+ ]);
+ });
+
+ test('suggests all basic x y charts when switching from another x y chart with multiple layers', () => {
+ (generateId as jest.Mock).mockReturnValueOnce('aaa');
+ const suggestions = getSuggestions({
+ table: {
+ isMultiRow: true,
+ columns: [numCol('bytes'), dateCol('date')],
+ layerId: 'first',
+ changeType: 'unchanged',
+ },
+ keptLayerIds: ['first', 'second'],
+ state: {
+ legend: { isVisible: true, position: 'bottom' },
+ preferredSeriesType: 'bar',
+ layers: [
+ {
+ layerId: 'first',
+ seriesType: 'bar',
+ xAccessor: 'date',
+ accessors: ['bytes'],
+ splitAccessor: undefined,
+ },
+ {
+ layerId: 'second',
+ seriesType: 'bar',
+ xAccessor: undefined,
+ accessors: [],
+ splitAccessor: undefined,
+ },
+ ],
+ },
+ });
+
+ expect(suggestions).toHaveLength(visualizationTypes.length);
+ expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([
'line',
'bar',
'bar_horizontal',
@@ -165,6 +236,15 @@ describe('xy_suggestions', () => {
'area',
'area_stacked',
]);
+ expect(suggestions.map(({ state }) => state.layers.map((l) => l.layerId))).toEqual([
+ ['first', 'second'],
+ ['first', 'second'],
+ ['first', 'second'],
+ ['first', 'second'],
+ ['first', 'second'],
+ ['first', 'second'],
+ ['first', 'second'],
+ ]);
});
test('suggests all basic x y chart with date on x', () => {
@@ -388,7 +468,7 @@ describe('xy_suggestions', () => {
changeType: 'unchanged',
},
state: currentState,
- keptLayerIds: [],
+ keptLayerIds: ['first'],
});
expect(rest).toHaveLength(visualizationTypes.length - 2);
@@ -497,7 +577,7 @@ describe('xy_suggestions', () => {
changeType: 'extended',
},
state: currentState,
- keptLayerIds: [],
+ keptLayerIds: ['first'],
});
expect(rest).toHaveLength(0);
@@ -536,7 +616,7 @@ describe('xy_suggestions', () => {
changeType: 'reorder',
},
state: currentState,
- keptLayerIds: [],
+ keptLayerIds: ['first'],
});
expect(rest).toHaveLength(0);
@@ -576,7 +656,7 @@ describe('xy_suggestions', () => {
changeType: 'extended',
},
state: currentState,
- keptLayerIds: [],
+ keptLayerIds: ['first'],
});
expect(rest).toHaveLength(0);
diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
index e0bfbd266f8f1..d7348f00bf8b8 100644
--- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
@@ -394,17 +394,25 @@ function buildSuggestion({
: undefined,
};
+ // Maintain consistent order for any layers that were saved
const keptLayers = currentState
- ? currentState.layers.filter(
- (layer) => layer.layerId !== layerId && keptLayerIds.includes(layer.layerId)
- )
+ ? currentState.layers
+ // Remove layers that aren't being suggested
+ .filter((layer) => keptLayerIds.includes(layer.layerId))
+ // Update in place
+ .map((layer) => (layer.layerId === layerId ? newLayer : layer))
+ // Replace the seriesType on all previous layers
+ .map((layer) => ({
+ ...layer,
+ seriesType,
+ }))
: [];
const state: State = {
legend: currentState ? currentState.legend : { isVisible: true, position: Position.Right },
fittingFunction: currentState?.fittingFunction || 'None',
preferredSeriesType: seriesType,
- layers: [...keptLayers, newLayer],
+ layers: Object.keys(existingLayer).length ? keptLayers : [...keptLayers, newLayer],
};
return {
diff --git a/x-pack/plugins/lens/server/saved_objects.ts b/x-pack/plugins/lens/server/saved_objects.ts
index a16cc3dab7967..82ee490bb22af 100644
--- a/x-pack/plugins/lens/server/saved_objects.ts
+++ b/x-pack/plugins/lens/server/saved_objects.ts
@@ -40,6 +40,7 @@ export function setupSavedObjects(core: CoreSetup) {
},
expression: {
index: false,
+ doc_values: false,
type: 'keyword',
},
},
diff --git a/x-pack/plugins/lists/common/constants.mock.ts b/x-pack/plugins/lists/common/constants.mock.ts
index 4924ba24426af..6ed1d19611c68 100644
--- a/x-pack/plugins/lists/common/constants.mock.ts
+++ b/x-pack/plugins/lists/common/constants.mock.ts
@@ -60,3 +60,4 @@ export const TAGS = [];
export const COMMENTS = [];
export const FILTER = 'name:Nicolas Bourbaki';
export const CURSOR = 'c29tZXN0cmluZ2ZvcnlvdQ==';
+export const _VERSION = 'WzI5NywxXQ==';
diff --git a/x-pack/plugins/lists/common/schemas/common/schemas.ts b/x-pack/plugins/lists/common/schemas/common/schemas.ts
index 6199a5f16f109..8f1666bb542d9 100644
--- a/x-pack/plugins/lists/common/schemas/common/schemas.ts
+++ b/x-pack/plugins/lists/common/schemas/common/schemas.ts
@@ -307,3 +307,7 @@ export type Deserializer = t.TypeOf;
export const deserializerOrUndefined = t.union([deserializer, t.undefined]);
export type DeserializerOrUndefined = t.TypeOf;
+
+export const _version = t.string;
+export const _versionOrUndefined = t.union([_version, t.undefined]);
+export type _VersionOrUndefined = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/schemas/elastic_query/create_es_bulk_type.ts b/x-pack/plugins/lists/common/schemas/elastic_query/create_es_bulk_type.ts
index 4a825382c06e4..3104ee27c57de 100644
--- a/x-pack/plugins/lists/common/schemas/elastic_query/create_es_bulk_type.ts
+++ b/x-pack/plugins/lists/common/schemas/elastic_query/create_es_bulk_type.ts
@@ -14,4 +14,4 @@ export const createEsBulkTypeSchema = t.exact(
})
);
-export type CreateEsBulkTypeSchema = t.TypeOf;
+export type CreateEsBulkTypeSchema = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_item_schema.ts
index 006600ee5b7fd..8dc5a376d1495 100644
--- a/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_item_schema.ts
@@ -38,4 +38,4 @@ export const indexEsListItemSchema = t.intersection([
esDataTypeUnion,
]);
-export type IndexEsListItemSchema = t.TypeOf;
+export type IndexEsListItemSchema = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_schema.ts b/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_schema.ts
index fd1018bc46a8d..3ee598291149f 100644
--- a/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/elastic_query/index_es_list_schema.ts
@@ -38,4 +38,4 @@ export const indexEsListSchema = t.exact(
})
);
-export type IndexEsListSchema = t.TypeOf;
+export type IndexEsListSchema = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_item_schema.ts
index e4cf46bc39429..20187de535a8e 100644
--- a/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_item_schema.ts
@@ -21,4 +21,4 @@ export const updateEsListItemSchema = t.intersection([
esDataTypeUnion,
]);
-export type UpdateEsListItemSchema = t.TypeOf;
+export type UpdateEsListItemSchema = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_schema.ts b/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_schema.ts
index 8f23f3744e563..80b9733908d39 100644
--- a/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/elastic_query/update_es_list_schema.ts
@@ -26,4 +26,4 @@ export const updateEsListSchema = t.exact(
})
);
-export type UpdateEsListSchema = t.TypeOf;
+export type UpdateEsListSchema = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.ts
index 5311c7a43cdb5..3f0e1a12894d4 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_endpoint_list_item_schema.ts
@@ -19,7 +19,7 @@ import {
name,
tags,
} from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import { CreateCommentsArray, DefaultCreateCommentsArray, DefaultEntryArray } from '../types';
import { EntriesArray } from '../types/entries';
import { DefaultUuid } from '../../siem_common_deps';
@@ -44,20 +44,16 @@ export const createEndpointListItemSchema = t.intersection([
),
]);
-export type CreateEndpointListItemSchemaPartial = Identity<
- t.TypeOf
->;
-export type CreateEndpointListItemSchema = RequiredKeepUndefined<
- t.TypeOf
->;
+export type CreateEndpointListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type CreateEndpointListItemSchemaDecoded = Identity<
- Omit & {
- _tags: _Tags;
- comments: CreateCommentsArray;
- tags: Tags;
- item_id: ItemId;
- entries: EntriesArray;
- }
->;
+export type CreateEndpointListItemSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ '_tags' | 'tags' | 'item_id' | 'entries' | 'comments'
+> & {
+ _tags: _Tags;
+ comments: CreateCommentsArray;
+ tags: Tags;
+ item_id: ItemId;
+ entries: EntriesArray;
+};
diff --git a/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.ts
index 4b7db3eee35bc..c2ccf18ed8720 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.ts
@@ -21,7 +21,7 @@ import {
namespace_type,
tags,
} from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import {
CreateCommentsArray,
DefaultCreateCommentsArray,
@@ -53,24 +53,17 @@ export const createExceptionListItemSchema = t.intersection([
),
]);
-export type CreateExceptionListItemSchemaPartial = Identity<
- t.TypeOf
->;
-export type CreateExceptionListItemSchema = RequiredKeepUndefined<
- t.TypeOf
->;
+export type CreateExceptionListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type CreateExceptionListItemSchemaDecoded = Identity<
- Omit<
- CreateExceptionListItemSchema,
- '_tags' | 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments'
- > & {
- _tags: _Tags;
- comments: CreateCommentsArray;
- tags: Tags;
- item_id: ItemId;
- entries: EntriesArray;
- namespace_type: NamespaceType;
- }
->;
+export type CreateExceptionListItemSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ '_tags' | 'tags' | 'item_id' | 'entries' | 'namespace_type' | 'comments'
+> & {
+ _tags: _Tags;
+ comments: CreateCommentsArray;
+ tags: Tags;
+ item_id: ItemId;
+ entries: EntriesArray;
+ namespace_type: NamespaceType;
+};
diff --git a/x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.ts
index 66cca4ab9ca53..8f714760621ff 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.ts
@@ -20,7 +20,7 @@ import {
namespace_type,
tags,
} from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import { DefaultUuid } from '../../siem_common_deps';
import { NamespaceType } from '../types';
@@ -43,17 +43,15 @@ export const createExceptionListSchema = t.intersection([
),
]);
-export type CreateExceptionListSchemaPartial = Identity>;
-export type CreateExceptionListSchema = RequiredKeepUndefined<
- t.TypeOf
->;
+export type CreateExceptionListSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type CreateExceptionListSchemaDecoded = Identity<
- Omit & {
- _tags: _Tags;
- tags: Tags;
- list_id: ListId;
- namespace_type: NamespaceType;
- }
->;
+export type CreateExceptionListSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ '_tags' | 'tags' | 'list_id' | 'namespace_type'
+> & {
+ _tags: _Tags;
+ tags: Tags;
+ list_id: ListId;
+ namespace_type: NamespaceType;
+};
diff --git a/x-pack/plugins/lists/common/schemas/request/create_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/create_list_item_schema.ts
index 6d16f2074864c..351eae48a638d 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_list_item_schema.ts
@@ -9,7 +9,7 @@
import * as t from 'io-ts';
import { id, list_id, meta, value } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
export const createListItemSchema = t.intersection([
t.exact(
@@ -21,5 +21,7 @@ export const createListItemSchema = t.intersection([
t.exact(t.partial({ id, meta })),
]);
-export type CreateListItemSchemaPartial = Identity>;
-export type CreateListItemSchema = RequiredKeepUndefined>;
+export type CreateListItemSchema = t.OutputOf;
+export type CreateListItemSchemaDecoded = RequiredKeepUndefined<
+ t.TypeOf
+>;
diff --git a/x-pack/plugins/lists/common/schemas/request/create_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/create_list_schema.ts
index fcf4465f88c8d..38d6167ea63f3 100644
--- a/x-pack/plugins/lists/common/schemas/request/create_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/create_list_schema.ts
@@ -7,7 +7,7 @@
import * as t from 'io-ts';
import { description, deserializer, id, meta, name, serializer, type } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
export const createListSchema = t.intersection([
t.exact(
@@ -20,5 +20,5 @@ export const createListSchema = t.intersection([
t.exact(t.partial({ deserializer, id, meta, serializer })),
]);
-export type CreateListSchemaPartial = Identity>;
-export type CreateListSchema = RequiredKeepUndefined>;
+export type CreateListSchema = t.OutputOf;
+export type CreateListSchemaDecoded = RequiredKeepUndefined>;
diff --git a/x-pack/plugins/lists/common/schemas/request/delete_endpoint_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/delete_endpoint_list_item_schema.ts
index 311af3a4c0437..5af5bcd17e744 100644
--- a/x-pack/plugins/lists/common/schemas/request/delete_endpoint_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/delete_endpoint_list_item_schema.ts
@@ -9,6 +9,7 @@
import * as t from 'io-ts';
import { id, item_id } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const deleteEndpointListItemSchema = t.exact(
t.partial({
@@ -17,7 +18,9 @@ export const deleteEndpointListItemSchema = t.exact(
})
);
-export type DeleteEndpointListItemSchema = t.TypeOf;
+export type DeleteEndpointListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type DeleteEndpointListItemSchemaDecoded = DeleteEndpointListItemSchema;
+export type DeleteEndpointListItemSchemaDecoded = RequiredKeepUndefined<
+ t.TypeOf
+>;
diff --git a/x-pack/plugins/lists/common/schemas/request/delete_exception_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/delete_exception_list_item_schema.ts
index 909960c9fffc0..da6516f4b6fe4 100644
--- a/x-pack/plugins/lists/common/schemas/request/delete_exception_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/delete_exception_list_item_schema.ts
@@ -10,6 +10,7 @@ import * as t from 'io-ts';
import { id, item_id, namespace_type } from '../common/schemas';
import { NamespaceType } from '../types';
+import { RequiredKeepUndefined } from '../../types';
export const deleteExceptionListItemSchema = t.exact(
t.partial({
@@ -19,11 +20,11 @@ export const deleteExceptionListItemSchema = t.exact(
})
);
-export type DeleteExceptionListItemSchema = t.TypeOf;
+export type DeleteExceptionListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
export type DeleteExceptionListItemSchemaDecoded = Omit<
- DeleteExceptionListItemSchema,
+ RequiredKeepUndefined>,
'namespace_type'
> & {
namespace_type: NamespaceType;
diff --git a/x-pack/plugins/lists/common/schemas/request/delete_exception_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/delete_exception_list_schema.ts
index 3bf5e7a4d0782..0911a9342f7a9 100644
--- a/x-pack/plugins/lists/common/schemas/request/delete_exception_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/delete_exception_list_schema.ts
@@ -10,6 +10,7 @@ import * as t from 'io-ts';
import { id, list_id, namespace_type } from '../common/schemas';
import { NamespaceType } from '../types';
+import { RequiredKeepUndefined } from '../../types';
export const deleteExceptionListSchema = t.exact(
t.partial({
@@ -19,9 +20,12 @@ export const deleteExceptionListSchema = t.exact(
})
);
-export type DeleteExceptionListSchema = t.TypeOf;
+export type DeleteExceptionListSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type DeleteExceptionListSchemaDecoded = Omit & {
+export type DeleteExceptionListSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ 'namespace_type'
+> & {
namespace_type: NamespaceType;
};
diff --git a/x-pack/plugins/lists/common/schemas/request/delete_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/delete_list_item_schema.ts
index 91887395e747d..5e2425271c463 100644
--- a/x-pack/plugins/lists/common/schemas/request/delete_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/delete_list_item_schema.ts
@@ -9,7 +9,7 @@
import * as t from 'io-ts';
import { id, list_id, valueOrUndefined } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
export const deleteListItemSchema = t.intersection([
t.exact(
@@ -20,5 +20,7 @@ export const deleteListItemSchema = t.intersection([
t.exact(t.partial({ id, list_id })),
]);
-export type DeleteListItemSchemaPartial = Identity>;
-export type DeleteListItemSchema = RequiredKeepUndefined>;
+export type DeleteListItemSchema = t.OutputOf;
+export type DeleteListItemSchemaDecoded = RequiredKeepUndefined<
+ t.TypeOf
+>;
diff --git a/x-pack/plugins/lists/common/schemas/request/delete_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/delete_list_schema.ts
index 6f6fc7a9ea33c..830e7fe695d1d 100644
--- a/x-pack/plugins/lists/common/schemas/request/delete_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/delete_list_schema.ts
@@ -9,6 +9,7 @@
import * as t from 'io-ts';
import { id } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const deleteListSchema = t.exact(
t.type({
@@ -16,5 +17,5 @@ export const deleteListSchema = t.exact(
})
);
-export type DeleteListSchema = t.TypeOf;
+export type DeleteListSchema = RequiredKeepUndefined>;
export type DeleteListSchemaEncoded = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/export_list_item_query_schema.ts b/x-pack/plugins/lists/common/schemas/request/export_list_item_query_schema.ts
index 58092ffc563b1..8d14f015d3805 100644
--- a/x-pack/plugins/lists/common/schemas/request/export_list_item_query_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/export_list_item_query_schema.ts
@@ -9,6 +9,7 @@
import * as t from 'io-ts';
import { list_id } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const exportListItemQuerySchema = t.exact(
t.type({
@@ -17,5 +18,7 @@ export const exportListItemQuerySchema = t.exact(
})
);
-export type ExportListItemQuerySchema = t.TypeOf;
+export type ExportListItemQuerySchema = RequiredKeepUndefined<
+ t.TypeOf
+>;
export type ExportListItemQuerySchemaEncoded = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.mock.ts
index bff55dedf3064..469936eae96c9 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.mock.ts
@@ -7,11 +7,11 @@
import { FILTER } from '../../constants.mock';
import {
- FindEndpointListItemSchemaPartial,
- FindEndpointListItemSchemaPartialDecoded,
+ FindEndpointListItemSchema,
+ FindEndpointListItemSchemaDecoded,
} from './find_endpoint_list_item_schema';
-export const getFindEndpointListItemSchemaMock = (): FindEndpointListItemSchemaPartial => ({
+export const getFindEndpointListItemSchemaMock = (): FindEndpointListItemSchema => ({
filter: FILTER,
page: '1',
per_page: '25',
@@ -19,7 +19,7 @@ export const getFindEndpointListItemSchemaMock = (): FindEndpointListItemSchemaP
sort_order: undefined,
});
-export const getFindEndpointListItemSchemaDecodedMock = (): FindEndpointListItemSchemaPartialDecoded => ({
+export const getFindEndpointListItemSchemaDecodedMock = (): FindEndpointListItemSchemaDecoded => ({
filter: FILTER,
page: 1,
per_page: 25,
diff --git a/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.test.ts
index f9eeaa33230f9..8249b1e2d49c2 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.test.ts
@@ -14,7 +14,7 @@ import {
getFindEndpointListItemSchemaMock,
} from './find_endpoint_list_item_schema.mock';
import {
- FindEndpointListItemSchemaPartial,
+ FindEndpointListItemSchema,
findEndpointListItemSchema,
} from './find_endpoint_list_item_schema';
@@ -29,7 +29,7 @@ describe('find_endpoint_list_item_schema', () => {
});
test('it should validate and empty object since everything is optional and has defaults', () => {
- const payload: FindEndpointListItemSchemaPartial = {};
+ const payload: FindEndpointListItemSchema = {};
const decoded = findEndpointListItemSchema.decode(payload);
const checked = exactCheck(payload, decoded);
const message = pipe(checked, foldLeftRight);
@@ -98,7 +98,7 @@ describe('find_endpoint_list_item_schema', () => {
});
test('it should not allow an extra key to be sent in', () => {
- const payload: FindEndpointListItemSchemaPartial & {
+ const payload: FindEndpointListItemSchema & {
extraKey: string;
} = { ...getFindEndpointListItemSchemaMock(), extraKey: 'some new value' };
const decoded = findEndpointListItemSchema.decode(payload);
diff --git a/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.ts
index c9ee46994d720..bc839ce1346f3 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_endpoint_list_item_schema.ts
@@ -22,16 +22,9 @@ export const findEndpointListItemSchema = t.exact(
})
);
-export type FindEndpointListItemSchemaPartial = t.OutputOf;
-
-// This type is used after a decode since some things are defaults after a decode.
-export type FindEndpointListItemSchemaPartialDecoded = t.TypeOf;
+export type FindEndpointListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
export type FindEndpointListItemSchemaDecoded = RequiredKeepUndefined<
- FindEndpointListItemSchemaPartialDecoded
->;
-
-export type FindEndpointListItemSchema = RequiredKeepUndefined<
t.TypeOf
>;
diff --git a/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.mock.ts
index f22e6685fe0ac..d2733531eada4 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.mock.ts
@@ -7,11 +7,11 @@
import { FILTER, LIST_ID, NAMESPACE_TYPE } from '../../constants.mock';
import {
- FindExceptionListItemSchemaPartial,
- FindExceptionListItemSchemaPartialDecoded,
+ FindExceptionListItemSchema,
+ FindExceptionListItemSchemaDecoded,
} from './find_exception_list_item_schema';
-export const getFindExceptionListItemSchemaMock = (): FindExceptionListItemSchemaPartial => ({
+export const getFindExceptionListItemSchemaMock = (): FindExceptionListItemSchema => ({
filter: FILTER,
list_id: LIST_ID,
namespace_type: NAMESPACE_TYPE,
@@ -21,7 +21,7 @@ export const getFindExceptionListItemSchemaMock = (): FindExceptionListItemSchem
sort_order: undefined,
});
-export const getFindExceptionListItemSchemaMultipleMock = (): FindExceptionListItemSchemaPartial => ({
+export const getFindExceptionListItemSchemaMultipleMock = (): FindExceptionListItemSchema => ({
filter: 'name:Sofia Kovalevskaya,name:Hypatia,name:Sophie Germain',
list_id: 'list-1,list-2,list-3',
namespace_type: 'single,single,agnostic',
@@ -31,7 +31,7 @@ export const getFindExceptionListItemSchemaMultipleMock = (): FindExceptionListI
sort_order: undefined,
});
-export const getFindExceptionListItemSchemaDecodedMock = (): FindExceptionListItemSchemaPartialDecoded => ({
+export const getFindExceptionListItemSchemaDecodedMock = (): FindExceptionListItemSchemaDecoded => ({
filter: [FILTER],
list_id: [LIST_ID],
namespace_type: [NAMESPACE_TYPE],
@@ -41,7 +41,7 @@ export const getFindExceptionListItemSchemaDecodedMock = (): FindExceptionListIt
sort_order: undefined,
});
-export const getFindExceptionListItemSchemaDecodedMultipleMock = (): FindExceptionListItemSchemaPartialDecoded => ({
+export const getFindExceptionListItemSchemaDecodedMultipleMock = (): FindExceptionListItemSchemaDecoded => ({
filter: ['name:Sofia Kovalevskaya', 'name:Hypatia', 'name:Sophie Germain'],
list_id: ['list-1', 'list-2', 'list-3'],
namespace_type: ['single', 'single', 'agnostic'],
diff --git a/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.test.ts
index ba64bb434d50b..f402f22b093ad 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.test.ts
@@ -17,8 +17,8 @@ import {
getFindExceptionListItemSchemaMultipleMock,
} from './find_exception_list_item_schema.mock';
import {
- FindExceptionListItemSchemaPartial,
- FindExceptionListItemSchemaPartialDecoded,
+ FindExceptionListItemSchema,
+ FindExceptionListItemSchemaDecoded,
findExceptionListItemSchema,
} from './find_exception_list_item_schema';
@@ -42,15 +42,19 @@ describe('find_list_item_schema', () => {
});
test('it should validate just a list_id where it decodes into an array for list_id and adds a namespace_type of "single" as an array', () => {
- const payload: FindExceptionListItemSchemaPartial = { list_id: LIST_ID };
+ const payload: FindExceptionListItemSchema = { list_id: LIST_ID };
const decoded = findExceptionListItemSchema.decode(payload);
const checked = exactCheck(payload, decoded);
const message = pipe(checked, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
- const expected: FindExceptionListItemSchemaPartialDecoded = {
+ const expected: FindExceptionListItemSchemaDecoded = {
filter: [],
list_id: [LIST_ID],
namespace_type: ['single'],
+ page: undefined,
+ per_page: undefined,
+ sort_field: undefined,
+ sort_order: undefined,
};
expect(message.schema).toEqual(expected);
});
@@ -86,7 +90,7 @@ describe('find_list_item_schema', () => {
const checked = exactCheck(payload, decoded);
const message = pipe(checked, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
- const expected: FindExceptionListItemSchemaPartialDecoded = {
+ const expected: FindExceptionListItemSchemaDecoded = {
...getFindExceptionListItemSchemaDecodedMock(),
filter: [],
};
@@ -118,7 +122,7 @@ describe('find_list_item_schema', () => {
});
test('it should not allow an extra key to be sent in', () => {
- const payload: FindExceptionListItemSchemaPartial & {
+ const payload: FindExceptionListItemSchema & {
extraKey: string;
} = { ...getFindExceptionListItemSchemaMock(), extraKey: 'some new value' };
const decoded = findExceptionListItemSchema.decode(payload);
diff --git a/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.ts
index aa53fa0fd912c..634c080d70b75 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_exception_list_item_schema.ts
@@ -36,22 +36,13 @@ export const findExceptionListItemSchema = t.intersection([
),
]);
-export type FindExceptionListItemSchemaPartial = t.OutputOf;
+export type FindExceptionListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type FindExceptionListItemSchemaPartialDecoded = Omit<
- t.TypeOf,
+export type FindExceptionListItemSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
'namespace_type' | 'filter'
> & {
filter: EmptyStringArrayDecoded;
namespace_type: DefaultNamespaceArrayTypeDecoded;
};
-
-// This type is used after a decode since some things are defaults after a decode.
-export type FindExceptionListItemSchemaDecoded = RequiredKeepUndefined<
- FindExceptionListItemSchemaPartialDecoded
->;
-
-export type FindExceptionListItemSchema = RequiredKeepUndefined<
- t.TypeOf
->;
diff --git a/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.mock.ts
index 8080d10ca451c..96f4b7e1cbd63 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.mock.ts
@@ -7,11 +7,11 @@
import { FILTER, NAMESPACE_TYPE } from '../../constants.mock';
import {
- FindExceptionListSchemaPartial,
- FindExceptionListSchemaPartialDecoded,
+ FindExceptionListSchema,
+ FindExceptionListSchemaDecoded,
} from './find_exception_list_schema';
-export const getFindExceptionListSchemaMock = (): FindExceptionListSchemaPartial => ({
+export const getFindExceptionListSchemaMock = (): FindExceptionListSchema => ({
filter: FILTER,
namespace_type: NAMESPACE_TYPE,
page: '1',
@@ -20,7 +20,7 @@ export const getFindExceptionListSchemaMock = (): FindExceptionListSchemaPartial
sort_order: undefined,
});
-export const getFindExceptionListSchemaDecodedMock = (): FindExceptionListSchemaPartialDecoded => ({
+export const getFindExceptionListSchemaDecodedMock = (): FindExceptionListSchemaDecoded => ({
filter: FILTER,
namespace_type: NAMESPACE_TYPE,
page: 1,
diff --git a/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.test.ts
index 42356066176d5..ef96346c732b8 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.test.ts
@@ -14,8 +14,8 @@ import {
getFindExceptionListSchemaMock,
} from './find_exception_list_schema.mock';
import {
- FindExceptionListSchemaPartial,
- FindExceptionListSchemaPartialDecoded,
+ FindExceptionListSchema,
+ FindExceptionListSchemaDecoded,
findExceptionListSchema,
} from './find_exception_list_schema';
@@ -30,13 +30,18 @@ describe('find_exception_list_schema', () => {
});
test('it should validate and empty object since everything is optional and will respond only with namespace_type filled out to be "single"', () => {
- const payload: FindExceptionListSchemaPartial = {};
+ const payload: FindExceptionListSchema = {};
const decoded = findExceptionListSchema.decode(payload);
const checked = exactCheck(payload, decoded);
const message = pipe(checked, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
- const expected: FindExceptionListSchemaPartialDecoded = {
+ const expected: FindExceptionListSchemaDecoded = {
+ filter: undefined,
namespace_type: 'single',
+ page: undefined,
+ per_page: undefined,
+ sort_field: undefined,
+ sort_order: undefined,
};
expect(message.schema).toEqual(expected);
});
@@ -102,7 +107,7 @@ describe('find_exception_list_schema', () => {
});
test('it should not allow an extra key to be sent in', () => {
- const payload: FindExceptionListSchemaPartial & {
+ const payload: FindExceptionListSchema & {
extraKey: string;
} = { ...getFindExceptionListSchemaMock(), extraKey: 'some new value' };
const decoded = findExceptionListSchema.decode(payload);
diff --git a/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.ts
index 4fa9d2e42c5d1..7ce01c79bbe42 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_exception_list_schema.ts
@@ -24,21 +24,12 @@ export const findExceptionListSchema = t.exact(
})
);
-export type FindExceptionListSchemaPartial = t.OutputOf;
+export type FindExceptionListSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type FindExceptionListSchemaPartialDecoded = Omit<
- t.TypeOf,
+export type FindExceptionListSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
'namespace_type'
> & {
namespace_type: NamespaceType;
};
-
-// This type is used after a decode since some things are defaults after a decode.
-export type FindExceptionListSchemaDecoded = RequiredKeepUndefined<
- FindExceptionListSchemaPartialDecoded
->;
-
-export type FindExceptionListSchema = RequiredKeepUndefined<
- t.TypeOf
->;
diff --git a/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.mock.ts
index a1e91f6acd264..ccde93eec4580 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.mock.ts
@@ -6,12 +6,9 @@
import { CURSOR, FILTER, LIST_ID } from '../../constants.mock';
-import {
- FindListItemSchemaPartial,
- FindListItemSchemaPartialDecoded,
-} from './find_list_item_schema';
+import { FindListItemSchema, FindListItemSchemaDecoded } from './find_list_item_schema';
-export const getFindListItemSchemaMock = (): FindListItemSchemaPartial => ({
+export const getFindListItemSchemaMock = (): FindListItemSchema => ({
cursor: CURSOR,
filter: FILTER,
list_id: LIST_ID,
@@ -21,7 +18,7 @@ export const getFindListItemSchemaMock = (): FindListItemSchemaPartial => ({
sort_order: undefined,
});
-export const getFindListItemSchemaDecodedMock = (): FindListItemSchemaPartialDecoded => ({
+export const getFindListItemSchemaDecodedMock = (): FindListItemSchemaDecoded => ({
cursor: CURSOR,
filter: FILTER,
list_id: LIST_ID,
diff --git a/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.test.ts
index 42803fffc53c2..59d4b4485b578 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.test.ts
@@ -15,8 +15,8 @@ import {
getFindListItemSchemaMock,
} from './find_list_item_schema.mock';
import {
- FindListItemSchemaPartial,
- FindListItemSchemaPartialDecoded,
+ FindListItemSchema,
+ FindListItemSchemaDecoded,
findListItemSchema,
} from './find_list_item_schema';
@@ -31,12 +31,12 @@ describe('find_list_item_schema', () => {
});
test('it should validate just a list_id where it decodes into an array for list_id and adds a namespace_type of "single"', () => {
- const payload: FindListItemSchemaPartial = { list_id: LIST_ID };
+ const payload: FindListItemSchema = { list_id: LIST_ID };
const decoded = findListItemSchema.decode(payload);
const checked = exactCheck(payload, decoded);
const message = pipe(checked, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
- const expected: FindListItemSchemaPartialDecoded = {
+ const expected: FindListItemSchemaDecoded = {
cursor: undefined,
filter: undefined,
list_id: LIST_ID,
@@ -97,7 +97,7 @@ describe('find_list_item_schema', () => {
});
test('it should not allow an extra key to be sent in', () => {
- const payload: FindListItemSchemaPartial & {
+ const payload: FindListItemSchema & {
extraKey: string;
} = { ...getFindListItemSchemaMock(), extraKey: 'some new value' };
const decoded = findListItemSchema.decode(payload);
diff --git a/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.ts
index bbd3c7b5ec642..ba3dfc6ee33ec 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_list_item_schema.ts
@@ -9,7 +9,7 @@
import * as t from 'io-ts';
import { cursor, filter, list_id, sort_field, sort_order } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import { StringToPositiveNumber } from '../types/string_to_positive_number';
export const findListItemSchema = t.intersection([
@@ -26,9 +26,7 @@ export const findListItemSchema = t.intersection([
),
]);
-export type FindListItemSchemaPartial = Identity>;
+export type FindListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type FindListItemSchemaPartialDecoded = RequiredKeepUndefined<
- t.TypeOf
->;
+export type FindListItemSchemaDecoded = RequiredKeepUndefined>;
diff --git a/x-pack/plugins/lists/common/schemas/request/find_list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/find_list_schema.mock.ts
index dcb18dac8cfb6..bb9e15a439b3b 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_list_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_list_schema.mock.ts
@@ -17,6 +17,7 @@ export const getFindListSchemaMock = (): FindListSchemaEncoded => ({
});
export const getFindListSchemaDecodedMock = (): FindListSchema => ({
+ cursor: undefined,
filter: FILTER,
page: 1,
per_page: 25,
diff --git a/x-pack/plugins/lists/common/schemas/request/find_list_schema.test.ts b/x-pack/plugins/lists/common/schemas/request/find_list_schema.test.ts
index a343fb4b08bfc..63f29a64b4bf9 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_list_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_list_schema.test.ts
@@ -10,7 +10,7 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { exactCheck, foldLeftRight, getPaths } from '../../siem_common_deps';
import { getFindListSchemaDecodedMock, getFindListSchemaMock } from './find_list_schema.mock';
-import { FindListSchema, FindListSchemaEncoded, findListSchema } from './find_list_schema';
+import { FindListSchemaEncoded, findListSchema } from './find_list_schema';
describe('find_list_schema', () => {
test('it should validate a typical find item request', () => {
@@ -28,8 +28,7 @@ describe('find_list_schema', () => {
const checked = exactCheck(payload, decoded);
const message = pipe(checked, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([]);
- const expected: FindListSchema = {};
- expect(message.schema).toEqual(expected);
+ expect(message.schema).toEqual(payload);
});
test('it should validate with page missing', () => {
diff --git a/x-pack/plugins/lists/common/schemas/request/find_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/find_list_schema.ts
index 212232f6bc9c1..e5020cc8eff84 100644
--- a/x-pack/plugins/lists/common/schemas/request/find_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/find_list_schema.ts
@@ -10,6 +10,7 @@ import * as t from 'io-ts';
import { cursor, filter, sort_field, sort_order } from '../common/schemas';
import { StringToPositiveNumber } from '../types/string_to_positive_number';
+import { RequiredKeepUndefined } from '../../types';
export const findListSchema = t.exact(
t.partial({
@@ -22,5 +23,5 @@ export const findListSchema = t.exact(
})
);
-export type FindListSchema = t.TypeOf;
+export type FindListSchema = RequiredKeepUndefined>;
export type FindListSchemaEncoded = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/import_list_item_query_schema.ts b/x-pack/plugins/lists/common/schemas/request/import_list_item_query_schema.ts
index 2c671466702e0..e45f77ca18ae1 100644
--- a/x-pack/plugins/lists/common/schemas/request/import_list_item_query_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/import_list_item_query_schema.ts
@@ -8,14 +8,14 @@
import * as t from 'io-ts';
+import { RequiredKeepUndefined } from '../../types';
import { deserializer, list_id, serializer, type } from '../common/schemas';
-import { Identity } from '../../types';
export const importListItemQuerySchema = t.exact(
t.partial({ deserializer, list_id, serializer, type })
);
-export type ImportListItemQuerySchemaPartial = Identity>;
-
-export type ImportListItemQuerySchema = t.TypeOf;
+export type ImportListItemQuerySchema = RequiredKeepUndefined<
+ t.TypeOf
+>;
export type ImportListItemQuerySchemaEncoded = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts
index 7370eecf690c7..671aeda757eff 100644
--- a/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts
@@ -9,6 +9,7 @@
import * as t from 'io-ts';
import { file } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const importListItemSchema = t.exact(
t.type({
@@ -16,5 +17,5 @@ export const importListItemSchema = t.exact(
})
);
-export type ImportListItemSchema = t.TypeOf;
+export type ImportListItemSchema = RequiredKeepUndefined>;
export type ImportListItemSchemaEncoded = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/patch_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/patch_list_item_schema.ts
index 2016069f32fb3..9c5284c15ca99 100644
--- a/x-pack/plugins/lists/common/schemas/request/patch_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/patch_list_item_schema.ts
@@ -8,8 +8,8 @@
import * as t from 'io-ts';
-import { id, meta, value } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { _version, id, meta, value } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const patchListItemSchema = t.intersection([
t.exact(
@@ -17,8 +17,10 @@ export const patchListItemSchema = t.intersection([
id,
})
),
- t.exact(t.partial({ meta, value })),
+ t.exact(t.partial({ _version, meta, value })),
]);
-export type PatchListItemSchemaPartial = Identity>;
-export type PatchListItemSchema = RequiredKeepUndefined>;
+export type PatchListItemSchema = t.OutputOf;
+export type PatchListItemSchemaDecoded = RequiredKeepUndefined<
+ t.TypeOf
+>;
diff --git a/x-pack/plugins/lists/common/schemas/request/patch_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/patch_list_schema.ts
index 653a42dc91653..e0cd1571afc81 100644
--- a/x-pack/plugins/lists/common/schemas/request/patch_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/patch_list_schema.ts
@@ -8,8 +8,8 @@
import * as t from 'io-ts';
-import { description, id, meta, name } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { _version, description, id, meta, name } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const patchListSchema = t.intersection([
t.exact(
@@ -17,8 +17,8 @@ export const patchListSchema = t.intersection([
id,
})
),
- t.exact(t.partial({ description, meta, name })),
+ t.exact(t.partial({ _version, description, meta, name })),
]);
-export type PatchListSchemaPartial = Identity>;
-export type PatchListSchema = RequiredKeepUndefined>>;
+export type PatchListSchema = t.OutputOf;
+export type PatchListSchemaDecoded = RequiredKeepUndefined>;
diff --git a/x-pack/plugins/lists/common/schemas/request/read_endpoint_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/read_endpoint_list_item_schema.ts
index 22750f5db6a1d..d6c54e289effe 100644
--- a/x-pack/plugins/lists/common/schemas/request/read_endpoint_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/read_endpoint_list_item_schema.ts
@@ -18,14 +18,9 @@ export const readEndpointListItemSchema = t.exact(
})
);
-export type ReadEndpointListItemSchemaPartial = t.TypeOf;
-
-// This type is used after a decode since some things are defaults after a decode.
-export type ReadEndpointListItemSchemaPartialDecoded = ReadEndpointListItemSchemaPartial;
+export type ReadEndpointListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
export type ReadEndpointListItemSchemaDecoded = RequiredKeepUndefined<
- ReadEndpointListItemSchemaPartialDecoded
+ t.TypeOf
>;
-
-export type ReadEndpointListItemSchema = RequiredKeepUndefined;
diff --git a/x-pack/plugins/lists/common/schemas/request/read_exception_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/read_exception_list_item_schema.ts
index d8864a6fc66e5..a2ba8126c7788 100644
--- a/x-pack/plugins/lists/common/schemas/request/read_exception_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/read_exception_list_item_schema.ts
@@ -20,19 +20,12 @@ export const readExceptionListItemSchema = t.exact(
})
);
-export type ReadExceptionListItemSchemaPartial = t.TypeOf;
+export type ReadExceptionListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type ReadExceptionListItemSchemaPartialDecoded = Omit<
- ReadExceptionListItemSchemaPartial,
+export type ReadExceptionListItemSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
'namespace_type'
> & {
namespace_type: NamespaceType;
};
-
-// This type is used after a decode since some things are defaults after a decode.
-export type ReadExceptionListItemSchemaDecoded = RequiredKeepUndefined<
- ReadExceptionListItemSchemaPartialDecoded
->;
-
-export type ReadExceptionListItemSchema = RequiredKeepUndefined;
diff --git a/x-pack/plugins/lists/common/schemas/request/read_exception_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/read_exception_list_schema.ts
index 613fb22a99d61..f22eca6a8ab15 100644
--- a/x-pack/plugins/lists/common/schemas/request/read_exception_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/read_exception_list_schema.ts
@@ -20,19 +20,12 @@ export const readExceptionListSchema = t.exact(
})
);
-export type ReadExceptionListSchemaPartial = t.TypeOf;
+export type ReadExceptionListSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type ReadExceptionListSchemaPartialDecoded = Omit<
- ReadExceptionListSchemaPartial,
+export type ReadExceptionListSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
'namespace_type'
> & {
namespace_type: NamespaceType;
};
-
-// This type is used after a decode since some things are defaults after a decode.
-export type ReadExceptionListSchemaDecoded = RequiredKeepUndefined<
- ReadExceptionListSchemaPartialDecoded
->;
-
-export type ReadExceptionListSchema = RequiredKeepUndefined;
diff --git a/x-pack/plugins/lists/common/schemas/request/read_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/read_list_item_schema.ts
index 394c1f1e2289a..063f430aa9cea 100644
--- a/x-pack/plugins/lists/common/schemas/request/read_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/read_list_item_schema.ts
@@ -9,9 +9,9 @@
import * as t from 'io-ts';
import { id, list_id, value } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
export const readListItemSchema = t.exact(t.partial({ id, list_id, value }));
-export type ReadListItemSchemaPartial = Identity>;
-export type ReadListItemSchema = RequiredKeepUndefined>;
+export type ReadListItemSchema = t.OutputOf;
+export type ReadListItemSchemaDecoded = RequiredKeepUndefined>;
diff --git a/x-pack/plugins/lists/common/schemas/request/read_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/read_list_schema.ts
index 8803346709c31..e395875462cb4 100644
--- a/x-pack/plugins/lists/common/schemas/request/read_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/read_list_schema.ts
@@ -16,4 +16,4 @@ export const readListSchema = t.exact(
})
);
-export type ReadListSchema = t.TypeOf;
+export type ReadListSchema = t.OutputOf;
diff --git a/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.mock.ts
index 30bbbe2d22ea4..0847389dac922 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.mock.ts
@@ -21,6 +21,7 @@ import { UpdateEndpointListItemSchema } from './update_endpoint_list_item_schema
export const getUpdateEndpointListItemSchemaMock = (): UpdateEndpointListItemSchema => ({
_tags: _TAGS,
+ _version: undefined,
comments: COMMENTS,
description: DESCRIPTION,
entries: ENTRIES,
diff --git a/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.ts
index dbe38f6d468e2..4430aa98b8e3d 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_endpoint_list_item_schema.ts
@@ -12,6 +12,7 @@ import {
Tags,
_Tags,
_tags,
+ _version,
description,
exceptionListItemType,
id,
@@ -19,7 +20,7 @@ import {
name,
tags,
} from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import {
DefaultEntryArray,
DefaultUpdateCommentsArray,
@@ -38,6 +39,7 @@ export const updateEndpointListItemSchema = t.intersection([
t.exact(
t.partial({
_tags, // defaults to empty array if not set during decode
+ _version, // defaults to undefined if not set during decode
comments: DefaultUpdateCommentsArray, // defaults to empty array if not set during decode
entries: DefaultEntryArray, // defaults to empty array if not set during decode
id, // defaults to undefined if not set during decode
@@ -48,19 +50,15 @@ export const updateEndpointListItemSchema = t.intersection([
),
]);
-export type UpdateEndpointListItemSchemaPartial = Identity<
- t.TypeOf
->;
-export type UpdateEndpointListItemSchema = RequiredKeepUndefined<
- t.TypeOf
->;
+export type UpdateEndpointListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type UpdateEndpointListItemSchemaDecoded = Identity<
- Omit & {
- _tags: _Tags;
- comments: UpdateCommentsArray;
- tags: Tags;
- entries: EntriesArray;
- }
->;
+export type UpdateEndpointListItemSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ '_tags' | 'tags' | 'entries' | 'comments'
+> & {
+ _tags: _Tags;
+ comments: UpdateCommentsArray;
+ tags: Tags;
+ entries: EntriesArray;
+};
diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts
index e8936f0bdc6d4..90d70c273f490 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.mock.ts
@@ -22,6 +22,7 @@ import { UpdateExceptionListItemSchema } from './update_exception_list_item_sche
export const getUpdateExceptionListItemSchemaMock = (): UpdateExceptionListItemSchema => ({
_tags: _TAGS,
+ _version: undefined,
comments: COMMENTS,
description: DESCRIPTION,
entries: ENTRIES,
diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.ts
index 20a63e0fc7dac..9e0a1759fc9f4 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_exception_list_item_schema.ts
@@ -12,6 +12,7 @@ import {
Tags,
_Tags,
_tags,
+ _version,
description,
exceptionListItemType,
id,
@@ -20,7 +21,7 @@ import {
namespace_type,
tags,
} from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import {
DefaultEntryArray,
DefaultUpdateCommentsArray,
@@ -40,6 +41,7 @@ export const updateExceptionListItemSchema = t.intersection([
t.exact(
t.partial({
_tags, // defaults to empty array if not set during decode
+ _version, // defaults to undefined if not set during decode
comments: DefaultUpdateCommentsArray, // defaults to empty array if not set during decode
entries: DefaultEntryArray, // defaults to empty array if not set during decode
id, // defaults to undefined if not set during decode
@@ -51,23 +53,16 @@ export const updateExceptionListItemSchema = t.intersection([
),
]);
-export type UpdateExceptionListItemSchemaPartial = Identity<
- t.TypeOf
->;
-export type UpdateExceptionListItemSchema = RequiredKeepUndefined<
- t.TypeOf
->;
+export type UpdateExceptionListItemSchema = t.OutputOf;
// This type is used after a decode since some things are defaults after a decode.
-export type UpdateExceptionListItemSchemaDecoded = Identity<
- Omit<
- UpdateExceptionListItemSchema,
- '_tags' | 'tags' | 'entries' | 'namespace_type' | 'comments'
- > & {
- _tags: _Tags;
- comments: UpdateCommentsArray;
- tags: Tags;
- entries: EntriesArray;
- namespace_type: NamespaceType;
- }
->;
+export type UpdateExceptionListItemSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ '_tags' | 'tags' | 'entries' | 'namespace_type' | 'comments'
+> & {
+ _tags: _Tags;
+ comments: UpdateCommentsArray;
+ tags: Tags;
+ entries: EntriesArray;
+ namespace_type: NamespaceType;
+};
diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts
index 48a8baf9aea16..22af29e6af0b7 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.mock.ts
@@ -10,6 +10,7 @@ import { UpdateExceptionListSchema } from './update_exception_list_schema';
export const getUpdateExceptionListSchemaMock = (): UpdateExceptionListSchema => ({
_tags: _TAGS,
+ _version: undefined,
description: DESCRIPTION,
id: ID,
list_id: LIST_ID,
diff --git a/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.ts
index 0b5f3a8a01794..5d7294ae27af2 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_exception_list_schema.ts
@@ -12,14 +12,17 @@ import {
Tags,
_Tags,
_tags,
+ _version,
description,
exceptionListType,
+ id,
+ list_id,
meta,
name,
namespace_type,
tags,
} from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { RequiredKeepUndefined } from '../../types';
import { NamespaceType } from '../types';
export const updateExceptionListSchema = t.intersection([
@@ -33,8 +36,9 @@ export const updateExceptionListSchema = t.intersection([
t.exact(
t.partial({
_tags, // defaults to empty array if not set during decode
- id: t.union([t.string, t.undefined]), // defaults to undefined if not set during decode
- list_id: t.union([t.string, t.undefined]), // defaults to undefined if not set during decode
+ _version, // defaults to undefined if not set during decode
+ id, // defaults to undefined if not set during decode
+ list_id, // defaults to undefined if not set during decode
meta, // defaults to undefined if not set during decode
namespace_type, // defaults to 'single' if not set during decode
tags, // defaults to empty array if not set during decode
@@ -42,16 +46,14 @@ export const updateExceptionListSchema = t.intersection([
),
]);
-export type UpdateExceptionListSchemaPartial = Identity>;
-export type UpdateExceptionListSchema = RequiredKeepUndefined<
- t.TypeOf
->;
+export type UpdateExceptionListSchema = t.OutputOf;
// This type is used after a decode since the arrays turn into defaults of empty arrays.
-export type UpdateExceptionListSchemaDecoded = Identity<
- Omit & {
- _tags: _Tags;
- tags: Tags;
- namespace_type: NamespaceType;
- }
->;
+export type UpdateExceptionListSchemaDecoded = Omit<
+ RequiredKeepUndefined>,
+ '_tags | tags | namespace_type'
+> & {
+ _tags: _Tags;
+ tags: Tags;
+ namespace_type: NamespaceType;
+};
diff --git a/x-pack/plugins/lists/common/schemas/request/update_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/update_list_item_schema.ts
index 3a42cf28665f5..c6ed5ef0e9517 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_list_item_schema.ts
@@ -8,8 +8,8 @@
import * as t from 'io-ts';
-import { id, meta, value } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { _version, id, meta, value } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const updateListItemSchema = t.intersection([
t.exact(
@@ -20,10 +20,13 @@ export const updateListItemSchema = t.intersection([
),
t.exact(
t.partial({
+ _version, // defaults to undefined if not set during decode
meta, // defaults to undefined if not set during decode
})
),
]);
-export type UpdateListItemSchemaPartial = Identity>;
-export type UpdateListItemSchema = RequiredKeepUndefined>;
+export type UpdateListItemSchema = t.OutputOf;
+export type UpdateListItemSchemaDecoded = RequiredKeepUndefined<
+ t.TypeOf
+>;
diff --git a/x-pack/plugins/lists/common/schemas/request/update_list_schema.ts b/x-pack/plugins/lists/common/schemas/request/update_list_schema.ts
index 4c5c8c429a14c..19a39d362c241 100644
--- a/x-pack/plugins/lists/common/schemas/request/update_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/request/update_list_schema.ts
@@ -8,8 +8,8 @@
import * as t from 'io-ts';
-import { description, id, meta, name } from '../common/schemas';
-import { Identity, RequiredKeepUndefined } from '../../types';
+import { _version, description, id, meta, name } from '../common/schemas';
+import { RequiredKeepUndefined } from '../../types';
export const updateListSchema = t.intersection([
t.exact(
@@ -21,10 +21,11 @@ export const updateListSchema = t.intersection([
),
t.exact(
t.partial({
+ _version, // defaults to undefined if not set during decode
meta, // defaults to undefined if not set during decode
})
),
]);
-export type UpdateListSchemaPartial = Identity>;
-export type UpdateListSchema = RequiredKeepUndefined>;
+export type UpdateListSchema = t.OutputOf;
+export type UpdateListSchemaDecoded = RequiredKeepUndefined>;
diff --git a/x-pack/plugins/lists/common/schemas/response/create_endpoint_list_schema.test.ts b/x-pack/plugins/lists/common/schemas/response/create_endpoint_list_schema.test.ts
index d346ea72ca310..646cc3d97f8ee 100644
--- a/x-pack/plugins/lists/common/schemas/response/create_endpoint_list_schema.test.ts
+++ b/x-pack/plugins/lists/common/schemas/response/create_endpoint_list_schema.test.ts
@@ -41,7 +41,7 @@ describe('create_endpoint_list_schema', () => {
const message = pipe(checked, foldLeftRight);
expect(getPaths(left(message.errors))).toEqual([
- 'invalid keys "_tags,["endpoint","process","malware","os:linux"],created_at,created_by,description,id,meta,{},name,namespace_type,tags,["user added string for a tag","malware"],tie_breaker_id,type,updated_at,updated_by"',
+ 'invalid keys "_tags,["endpoint","process","malware","os:linux"],_version,created_at,created_by,description,id,meta,{},name,namespace_type,tags,["user added string for a tag","malware"],tie_breaker_id,type,updated_at,updated_by"',
]);
expect(message.schema).toEqual({});
});
diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts
index f7a6af98c8f0e..c0d04c9823ca3 100644
--- a/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.mock.ts
@@ -3,26 +3,38 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { ENTRIES } from '../../constants.mock';
+import {
+ COMMENTS,
+ DATE_NOW,
+ DESCRIPTION,
+ ENTRIES,
+ ITEM_TYPE,
+ META,
+ NAME,
+ NAMESPACE_TYPE,
+ TIE_BREAKER,
+ USER,
+} from '../../constants.mock';
import { ExceptionListItemSchema } from './exception_list_item_schema';
export const getExceptionListItemSchemaMock = (): ExceptionListItemSchema => ({
_tags: ['endpoint', 'process', 'malware', 'os:linux'],
- comments: [],
- created_at: '2020-04-23T00:19:13.289Z',
- created_by: 'user_name',
- description: 'This is a sample endpoint type exception',
+ _version: undefined,
+ comments: COMMENTS,
+ created_at: DATE_NOW,
+ created_by: USER,
+ description: DESCRIPTION,
entries: ENTRIES,
id: '1',
item_id: 'endpoint_list_item',
- list_id: 'endpoint_list',
- meta: {},
- name: 'Sample Endpoint Exception List',
- namespace_type: 'single',
+ list_id: 'endpoint_list_id',
+ meta: META,
+ name: NAME,
+ namespace_type: NAMESPACE_TYPE,
tags: ['user added string for a tag', 'malware'],
- tie_breaker_id: '77fd1909-6786-428a-a671-30229a719c1f',
- type: 'simple',
- updated_at: '2020-04-23T00:19:13.289Z',
- updated_by: 'user_name',
+ tie_breaker_id: TIE_BREAKER,
+ type: ITEM_TYPE,
+ updated_at: DATE_NOW,
+ updated_by: USER,
});
diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.ts
index c8440e9d3f3d0..54907f3f8a854 100644
--- a/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/response/exception_list_item_schema.ts
@@ -10,6 +10,7 @@ import * as t from 'io-ts';
import {
_tags,
+ _versionOrUndefined,
created_at,
created_by,
description,
@@ -30,6 +31,7 @@ import { commentsArray, entriesArray } from '../types';
export const exceptionListItemSchema = t.exact(
t.type({
_tags,
+ _version: _versionOrUndefined,
comments: commentsArray,
created_at,
created_by,
diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts
index 017b959a2baf3..f790ad9544d53 100644
--- a/x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/response/exception_list_schema.mock.ts
@@ -4,21 +4,32 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ExceptionListSchema } from './exception_list_schema';
+import {
+ DATE_NOW,
+ DESCRIPTION,
+ ENDPOINT_TYPE,
+ META,
+ TIE_BREAKER,
+ USER,
+ _VERSION,
+} from '../../constants.mock';
+import { ENDPOINT_LIST_ID } from '../..';
+import { ExceptionListSchema } from './exception_list_schema';
export const getExceptionListSchemaMock = (): ExceptionListSchema => ({
_tags: ['endpoint', 'process', 'malware', 'os:linux'],
- created_at: '2020-04-23T00:19:13.289Z',
- created_by: 'user_name',
- description: 'This is a sample endpoint type exception',
+ _version: _VERSION,
+ created_at: DATE_NOW,
+ created_by: USER,
+ description: DESCRIPTION,
id: '1',
- list_id: 'endpoint_list',
- meta: {},
+ list_id: ENDPOINT_LIST_ID,
+ meta: META,
name: 'Sample Endpoint Exception List',
- namespace_type: 'single',
+ namespace_type: 'agnostic',
tags: ['user added string for a tag', 'malware'],
- tie_breaker_id: '77fd1909-6786-428a-a671-30229a719c1f',
- type: 'endpoint',
- updated_at: '2020-04-23T00:19:13.289Z',
+ tie_breaker_id: TIE_BREAKER,
+ type: ENDPOINT_TYPE,
+ updated_at: DATE_NOW,
updated_by: 'user_name',
});
diff --git a/x-pack/plugins/lists/common/schemas/response/exception_list_schema.ts b/x-pack/plugins/lists/common/schemas/response/exception_list_schema.ts
index 0fb2bfca4a48f..11c23bc2ff354 100644
--- a/x-pack/plugins/lists/common/schemas/response/exception_list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/response/exception_list_schema.ts
@@ -10,6 +10,7 @@ import * as t from 'io-ts';
import {
_tags,
+ _versionOrUndefined,
created_at,
created_by,
description,
@@ -28,6 +29,7 @@ import {
export const exceptionListSchema = t.exact(
t.type({
_tags,
+ _version: _versionOrUndefined,
created_at,
created_by,
description,
diff --git a/x-pack/plugins/lists/common/schemas/response/list_item_schema.mock.ts b/x-pack/plugins/lists/common/schemas/response/list_item_schema.mock.ts
index 16e8057974917..e122f6a2bbe3b 100644
--- a/x-pack/plugins/lists/common/schemas/response/list_item_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/response/list_item_schema.mock.ts
@@ -17,6 +17,7 @@ import {
} from '../../../common/constants.mock';
export const getListItemResponseMock = (): ListItemSchema => ({
+ _version: undefined,
created_at: DATE_NOW,
created_by: USER,
deserializer: undefined,
diff --git a/x-pack/plugins/lists/common/schemas/response/list_item_schema.ts b/x-pack/plugins/lists/common/schemas/response/list_item_schema.ts
index c2104aaf18b53..9ee801298f950 100644
--- a/x-pack/plugins/lists/common/schemas/response/list_item_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/response/list_item_schema.ts
@@ -9,6 +9,7 @@ import * as t from 'io-ts';
/* eslint-disable @typescript-eslint/camelcase */
import {
+ _versionOrUndefined,
created_at,
created_by,
deserializerOrUndefined,
@@ -25,6 +26,7 @@ import {
export const listItemSchema = t.exact(
t.type({
+ _version: _versionOrUndefined,
created_at,
created_by,
deserializer: deserializerOrUndefined,
diff --git a/x-pack/plugins/lists/common/schemas/response/list_schema.mock.ts b/x-pack/plugins/lists/common/schemas/response/list_schema.mock.ts
index c165c4ed8e745..339beddb00f8e 100644
--- a/x-pack/plugins/lists/common/schemas/response/list_schema.mock.ts
+++ b/x-pack/plugins/lists/common/schemas/response/list_schema.mock.ts
@@ -17,6 +17,7 @@ import {
} from '../../../common/constants.mock';
export const getListResponseMock = (): ListSchema => ({
+ _version: undefined,
created_at: DATE_NOW,
created_by: USER,
description: DESCRIPTION,
diff --git a/x-pack/plugins/lists/common/schemas/response/list_schema.ts b/x-pack/plugins/lists/common/schemas/response/list_schema.ts
index 1950831bee694..7e2bc202a6520 100644
--- a/x-pack/plugins/lists/common/schemas/response/list_schema.ts
+++ b/x-pack/plugins/lists/common/schemas/response/list_schema.ts
@@ -9,6 +9,7 @@
import * as t from 'io-ts';
import {
+ _versionOrUndefined,
created_at,
created_by,
description,
@@ -25,6 +26,7 @@ import {
export const listSchema = t.exact(
t.type({
+ _version: _versionOrUndefined,
created_at,
created_by,
description,
diff --git a/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts b/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts
index e8be299246ab8..342cf8b0d7091 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_comments_array.ts
@@ -9,17 +9,11 @@ import { Either } from 'fp-ts/lib/Either';
import { CommentsArray, comments } from './comments';
-export type DefaultCommentsArrayC = t.Type;
-
/**
* Types the DefaultCommentsArray as:
* - If null or undefined, then a default array of type entry will be set
*/
-export const DefaultCommentsArray: DefaultCommentsArrayC = new t.Type<
- CommentsArray,
- CommentsArray,
- unknown
->(
+export const DefaultCommentsArray = new t.Type(
'DefaultCommentsArray',
t.array(comments).is,
(input): Either =>
diff --git a/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts b/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts
index 51431b9c39850..7fd79782836e3 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_create_comments_array.ts
@@ -9,13 +9,11 @@ import { Either } from 'fp-ts/lib/Either';
import { CreateCommentsArray, createComments } from './create_comments';
-export type DefaultCreateCommentsArrayC = t.Type;
-
/**
* Types the DefaultCreateComments as:
* - If null or undefined, then a default array of type entry will be set
*/
-export const DefaultCreateCommentsArray: DefaultCreateCommentsArrayC = new t.Type<
+export const DefaultCreateCommentsArray = new t.Type<
CreateCommentsArray,
CreateCommentsArray,
unknown
diff --git a/x-pack/plugins/lists/common/schemas/types/default_entries_array.ts b/x-pack/plugins/lists/common/schemas/types/default_entries_array.ts
index da67fb286affa..a85fdf8537f39 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_entries_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_entries_array.ts
@@ -9,17 +9,11 @@ import { Either } from 'fp-ts/lib/Either';
import { EntriesArray, entriesArray } from './entries';
-export type DefaultEntriesArrayC = t.Type;
-
/**
* Types the DefaultEntriesArray as:
* - If null or undefined, then a default array of type entry will be set
*/
-export const DefaultEntryArray: DefaultEntriesArrayC = new t.Type<
- EntriesArray,
- EntriesArray,
- unknown
->(
+export const DefaultEntryArray = new t.Type(
'DefaultEntryArray',
entriesArray.is,
(input): Either =>
diff --git a/x-pack/plugins/lists/common/schemas/types/default_namespace.ts b/x-pack/plugins/lists/common/schemas/types/default_namespace.ts
index ecc45d3c84313..b61497a78aff0 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_namespace.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_namespace.ts
@@ -14,12 +14,10 @@ export type NamespaceType = t.TypeOf;
* Types the DefaultNamespace as:
* - If null or undefined, then a default string/enumeration of "single" will be used.
*/
-export const DefaultNamespace = new t.Type(
+export const DefaultNamespace = new t.Type(
'DefaultNamespace',
namespaceType.is,
(input, context): Either =>
input == null ? t.success('single') : namespaceType.validate(input, context),
t.identity
);
-
-export type DefaultNamespaceC = typeof DefaultNamespace;
diff --git a/x-pack/plugins/lists/common/schemas/types/default_namespace_array.test.ts b/x-pack/plugins/lists/common/schemas/types/default_namespace_array.test.ts
index 055f93069950e..255c89959b610 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_namespace_array.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_namespace_array.test.ts
@@ -9,11 +9,11 @@ import { left } from 'fp-ts/lib/Either';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
-import { DefaultNamespaceArray, DefaultNamespaceArrayTypeEncoded } from './default_namespace_array';
+import { DefaultNamespaceArray, DefaultNamespaceArrayType } from './default_namespace_array';
describe('default_namespace_array', () => {
test('it should validate "null" single item as an array with a "single" value', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = null;
+ const payload: DefaultNamespaceArrayType = null;
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -33,7 +33,7 @@ describe('default_namespace_array', () => {
});
test('it should validate "undefined" item as an array with a "single" value', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = undefined;
+ const payload: DefaultNamespaceArrayType = undefined;
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -42,7 +42,7 @@ describe('default_namespace_array', () => {
});
test('it should validate "single" as an array of a "single" value', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = 'single';
+ const payload: DefaultNamespaceArrayType = 'single';
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -51,7 +51,7 @@ describe('default_namespace_array', () => {
});
test('it should validate "agnostic" as an array of a "agnostic" value', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = 'agnostic';
+ const payload: DefaultNamespaceArrayType = 'agnostic';
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -60,7 +60,7 @@ describe('default_namespace_array', () => {
});
test('it should validate "single,agnostic" as an array of 2 values of ["single", "agnostic"] values', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = 'agnostic,single';
+ const payload: DefaultNamespaceArrayType = 'agnostic,single';
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -69,7 +69,7 @@ describe('default_namespace_array', () => {
});
test('it should validate 3 elements of "single,agnostic,single" as an array of 3 values of ["single", "agnostic", "single"] values', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = 'single,agnostic,single';
+ const payload: DefaultNamespaceArrayType = 'single,agnostic,single';
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -78,7 +78,7 @@ describe('default_namespace_array', () => {
});
test('it should validate 3 elements of "single,agnostic, single" as an array of 3 values of ["single", "agnostic", "single"] values when there are spaces', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = ' single, agnostic, single ';
+ const payload: DefaultNamespaceArrayType = ' single, agnostic, single ';
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -87,7 +87,7 @@ describe('default_namespace_array', () => {
});
test('it should not validate 3 elements of "single,agnostic,junk" since the 3rd value is junk', () => {
- const payload: DefaultNamespaceArrayTypeEncoded = 'single,agnostic,junk';
+ const payload: DefaultNamespaceArrayType = 'single,agnostic,junk';
const decoded = DefaultNamespaceArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
diff --git a/x-pack/plugins/lists/common/schemas/types/default_namespace_array.ts b/x-pack/plugins/lists/common/schemas/types/default_namespace_array.ts
index c4099a48ffbcc..b0ae85e65b22a 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_namespace_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_namespace_array.ts
@@ -39,7 +39,5 @@ export const DefaultNamespaceArray = new t.Type<
String
);
-export type DefaultNamespaceC = typeof DefaultNamespaceArray;
-
-export type DefaultNamespaceArrayTypeEncoded = t.OutputOf;
+export type DefaultNamespaceArrayType = t.OutputOf;
export type DefaultNamespaceArrayTypeDecoded = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts
index c2593826a6358..854b7cf7ada7e 100644
--- a/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/default_update_comments_array.ts
@@ -9,13 +9,11 @@ import { Either } from 'fp-ts/lib/Either';
import { UpdateCommentsArray, updateCommentsArray } from './update_comments';
-export type DefaultUpdateCommentsArrayC = t.Type;
-
/**
* Types the DefaultCommentsUpdate as:
* - If null or undefined, then a default array of type entry will be set
*/
-export const DefaultUpdateCommentsArray: DefaultUpdateCommentsArrayC = new t.Type<
+export const DefaultUpdateCommentsArray = new t.Type<
UpdateCommentsArray,
UpdateCommentsArray,
unknown
diff --git a/x-pack/plugins/lists/common/schemas/types/empty_string_array.ts b/x-pack/plugins/lists/common/schemas/types/empty_string_array.ts
index 389dc4a410cc9..bbaa66260e76e 100644
--- a/x-pack/plugins/lists/common/schemas/types/empty_string_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/empty_string_array.ts
@@ -39,7 +39,5 @@ export const EmptyStringArray = new t.Type;
export type EmptyStringArrayDecoded = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.test.ts b/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.test.ts
index 6124487cdd7fb..fac088568f85e 100644
--- a/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.test.ts
+++ b/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.test.ts
@@ -9,11 +9,11 @@ import { left } from 'fp-ts/lib/Either';
import { foldLeftRight, getPaths } from '../../siem_common_deps';
-import { NonEmptyStringArray, NonEmptyStringArrayEncoded } from './non_empty_string_array';
+import { NonEmptyStringArray } from './non_empty_string_array';
describe('non_empty_string_array', () => {
test('it should NOT validate "null"', () => {
- const payload: NonEmptyStringArrayEncoded | null = null;
+ const payload: NonEmptyStringArray | null = null;
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -24,7 +24,7 @@ describe('non_empty_string_array', () => {
});
test('it should NOT validate "undefined"', () => {
- const payload: NonEmptyStringArrayEncoded | undefined = undefined;
+ const payload: NonEmptyStringArray | undefined = undefined;
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -35,7 +35,7 @@ describe('non_empty_string_array', () => {
});
test('it should NOT validate a single value of an empty string ""', () => {
- const payload: NonEmptyStringArrayEncoded = '';
+ const payload: NonEmptyStringArray = '';
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -46,7 +46,7 @@ describe('non_empty_string_array', () => {
});
test('it should validate a single value of "a" into an array of size 1 of ["a"]', () => {
- const payload: NonEmptyStringArrayEncoded = 'a';
+ const payload: NonEmptyStringArray = 'a';
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -55,7 +55,7 @@ describe('non_empty_string_array', () => {
});
test('it should validate 2 values of "a,b" into an array of size 2 of ["a", "b"]', () => {
- const payload: NonEmptyStringArrayEncoded = 'a,b';
+ const payload: NonEmptyStringArray = 'a,b';
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -64,7 +64,7 @@ describe('non_empty_string_array', () => {
});
test('it should validate 3 values of "a,b,c" into an array of size 3 of ["a", "b", "c"]', () => {
- const payload: NonEmptyStringArrayEncoded = 'a,b,c';
+ const payload: NonEmptyStringArray = 'a,b,c';
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
@@ -84,7 +84,7 @@ describe('non_empty_string_array', () => {
});
test('it should validate 3 values of " a, b, c " into an array of size 3 of ["a", "b", "c"] even though they have spaces', () => {
- const payload: NonEmptyStringArrayEncoded = ' a, b, c ';
+ const payload: NonEmptyStringArray = ' a, b, c ';
const decoded = NonEmptyStringArray.decode(payload);
const message = pipe(decoded, foldLeftRight);
diff --git a/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.ts b/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.ts
index c4a640e7cdbad..90475f7935875 100644
--- a/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.ts
+++ b/x-pack/plugins/lists/common/schemas/types/non_empty_string_array.ts
@@ -35,7 +35,5 @@ export const NonEmptyStringArray = new t.Type(
String
);
-export type NonEmptyStringArrayC = typeof NonEmptyStringArray;
-
-export type NonEmptyStringArrayEncoded = t.OutputOf;
+export type NonEmptyStringArray = t.OutputOf;
export type NonEmptyStringArrayDecoded = t.TypeOf;
diff --git a/x-pack/plugins/lists/common/types.ts b/x-pack/plugins/lists/common/types.ts
index 1539c5ae01ff5..cee5567a55a6c 100644
--- a/x-pack/plugins/lists/common/types.ts
+++ b/x-pack/plugins/lists/common/types.ts
@@ -20,11 +20,3 @@ export type RequiredKeepUndefined = { [K in keyof T]-?: [T[K]] } extends infe
? { [K in keyof U]: U[K][0] }
: never
: never;
-
-/**
- * This is just a helper to cleanup nasty intersections and unions to make them
- * readable from io.ts, it's an identity that strips away the uglyness of them.
- */
-export type Identity = {
- [P in keyof T]: T[P];
-};
diff --git a/x-pack/plugins/lists/public/exceptions/api.test.ts b/x-pack/plugins/lists/public/exceptions/api.test.ts
index 1414d828fa6d4..455670098307f 100644
--- a/x-pack/plugins/lists/public/exceptions/api.test.ts
+++ b/x-pack/plugins/lists/public/exceptions/api.test.ts
@@ -508,7 +508,7 @@ describe('Exceptions Lists API', () => {
test('it returns expected format when call succeeds', async () => {
const exceptionResponse = await fetchExceptionListItemsByListId({
http: mockKibanaHttpService(),
- listId: 'endpoint_list',
+ listId: 'endpoint_list_id',
namespaceType: 'single',
pagination: {
page: 1,
diff --git a/x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts b/x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts
index b6eacc3b7dd04..5ff2a9d9df9f4 100644
--- a/x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_endpoint_list_item_route.ts
@@ -21,7 +21,7 @@ export const createEndpointListItemRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: ENDPOINT_LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts b/x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts
index cac69ce65623f..b1e589be67cd1 100644
--- a/x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_endpoint_list_route.ts
@@ -26,7 +26,7 @@ export const createEndpointListRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: ENDPOINT_LIST_URL,
validate: false,
diff --git a/x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts
index c331eeb4bd2d0..e4885c7393bd4 100644
--- a/x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_exception_list_item_route.ts
@@ -22,7 +22,7 @@ export const createExceptionListItemRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: EXCEPTION_LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/create_exception_list_route.ts b/x-pack/plugins/lists/server/routes/create_exception_list_route.ts
index bd29a65c9450a..897d82d6a9ba0 100644
--- a/x-pack/plugins/lists/server/routes/create_exception_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_exception_list_route.ts
@@ -21,7 +21,7 @@ export const createExceptionListRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: EXCEPTION_LIST_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/create_list_index_route.ts b/x-pack/plugins/lists/server/routes/create_list_index_route.ts
index 5ec2b36da61b0..1bffdd6bd5b5f 100644
--- a/x-pack/plugins/lists/server/routes/create_list_index_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_list_index_route.ts
@@ -17,7 +17,7 @@ export const createListIndexRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_INDEX,
validate: false,
diff --git a/x-pack/plugins/lists/server/routes/create_list_item_route.ts b/x-pack/plugins/lists/server/routes/create_list_item_route.ts
index 8ac5db3c7fd1c..656d6af2c6c9a 100644
--- a/x-pack/plugins/lists/server/routes/create_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_list_item_route.ts
@@ -17,7 +17,7 @@ export const createListItemRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/create_list_route.ts b/x-pack/plugins/lists/server/routes/create_list_route.ts
index eee7517523b0f..ff041699054c9 100644
--- a/x-pack/plugins/lists/server/routes/create_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/create_list_route.ts
@@ -17,7 +17,7 @@ export const createListRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts b/x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts
index b8946c542b27e..2d5028bd9525a 100644
--- a/x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_endpoint_list_item_route.ts
@@ -21,7 +21,7 @@ export const deleteEndpointListItemRoute = (router: IRouter): void => {
router.delete(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: ENDPOINT_LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts
index f363252dada50..06ff051925407 100644
--- a/x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_exception_list_item_route.ts
@@ -21,7 +21,7 @@ export const deleteExceptionListItemRoute = (router: IRouter): void => {
router.delete(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: EXCEPTION_LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/delete_exception_list_route.ts b/x-pack/plugins/lists/server/routes/delete_exception_list_route.ts
index b1bf705dcc5f6..f2bf517f55ae3 100644
--- a/x-pack/plugins/lists/server/routes/delete_exception_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_exception_list_route.ts
@@ -21,7 +21,7 @@ export const deleteExceptionListRoute = (router: IRouter): void => {
router.delete(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: EXCEPTION_LIST_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/delete_list_index_route.ts b/x-pack/plugins/lists/server/routes/delete_list_index_route.ts
index cb2e16b3602a7..be58d8aeed17d 100644
--- a/x-pack/plugins/lists/server/routes/delete_list_index_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_list_index_route.ts
@@ -33,7 +33,7 @@ export const deleteListIndexRoute = (router: IRouter): void => {
router.delete(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_INDEX,
validate: false,
diff --git a/x-pack/plugins/lists/server/routes/delete_list_item_route.ts b/x-pack/plugins/lists/server/routes/delete_list_item_route.ts
index bb278ba436725..50313cd1294ae 100644
--- a/x-pack/plugins/lists/server/routes/delete_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_list_item_route.ts
@@ -17,7 +17,7 @@ export const deleteListItemRoute = (router: IRouter): void => {
router.delete(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/delete_list_route.ts b/x-pack/plugins/lists/server/routes/delete_list_route.ts
index 600e4b00c29ca..4eeb6d8f126ad 100644
--- a/x-pack/plugins/lists/server/routes/delete_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_list_route.ts
@@ -17,7 +17,7 @@ export const deleteListRoute = (router: IRouter): void => {
router.delete(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/export_list_item_route.ts b/x-pack/plugins/lists/server/routes/export_list_item_route.ts
index 8148c9b1ed824..98167931c4346 100644
--- a/x-pack/plugins/lists/server/routes/export_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/export_list_item_route.ts
@@ -18,7 +18,7 @@ export const exportListItemRoute = (router: IRouter): void => {
router.post(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: `${LIST_ITEM_URL}/_export`,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts b/x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts
index 7374ff7dc92ea..9f83761cc501a 100644
--- a/x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/find_endpoint_list_item_route.ts
@@ -21,7 +21,7 @@ export const findEndpointListItemRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: `${ENDPOINT_LIST_ITEM_URL}/_find`,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts
index a318d653450c7..270aad85796b2 100644
--- a/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/find_exception_list_item_route.ts
@@ -21,7 +21,7 @@ export const findExceptionListItemRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: `${EXCEPTION_LIST_ITEM_URL}/_find`,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/find_exception_list_route.ts b/x-pack/plugins/lists/server/routes/find_exception_list_route.ts
index 97e1de834cd37..c5cae7a1e0bb8 100644
--- a/x-pack/plugins/lists/server/routes/find_exception_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/find_exception_list_route.ts
@@ -21,7 +21,7 @@ export const findExceptionListRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: `${EXCEPTION_LIST_URL}/_find`,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/find_list_item_route.ts b/x-pack/plugins/lists/server/routes/find_list_item_route.ts
index 52d534b08df2b..533dc74aa3694 100644
--- a/x-pack/plugins/lists/server/routes/find_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/find_list_item_route.ts
@@ -10,7 +10,7 @@ import { LIST_ITEM_URL } from '../../common/constants';
import { buildRouteValidation, buildSiemResponse, transformError } from '../siem_server_deps';
import { validate } from '../../common/siem_common_deps';
import {
- FindListItemSchemaPartialDecoded,
+ FindListItemSchemaDecoded,
findListItemSchema,
foundListItemSchema,
} from '../../common/schemas';
@@ -22,11 +22,11 @@ export const findListItemRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: `${LIST_ITEM_URL}/_find`,
validate: {
- query: buildRouteValidation(
+ query: buildRouteValidation