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 593e8f82f0541..ceb3ac4cca937 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.1",
"@elastic/ems-client": "7.9.3",
"@elastic/eui": "26.3.1",
"@elastic/filesaver": "1.1.2",
@@ -322,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",
@@ -411,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-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/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/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/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/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/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/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/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/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 9e1a88ceb28bd..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_id',
- meta: {},
- name: 'Sample Endpoint Exception List',
- namespace_type: 'single',
+ 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 906dcf6560ee5..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,23 +4,32 @@
* you may not use this file except in compliance with the Elastic License.
*/
+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_ID,
- meta: {},
+ meta: META,
name: 'Sample Endpoint Exception List',
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/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(
findListItemSchema
),
},
diff --git a/x-pack/plugins/lists/server/routes/find_list_route.ts b/x-pack/plugins/lists/server/routes/find_list_route.ts
index 2fa43c6368b5c..268eb36a5e26e 100644
--- a/x-pack/plugins/lists/server/routes/find_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/find_list_route.ts
@@ -18,7 +18,7 @@ export const findListRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: `${LIST_URL}/_find`,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/import_list_item_route.ts b/x-pack/plugins/lists/server/routes/import_list_item_route.ts
index 2e629d7516dd1..5e88ca0f2569a 100644
--- a/x-pack/plugins/lists/server/routes/import_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/import_list_item_route.ts
@@ -26,7 +26,7 @@ export const importListItemRoute = (router: IRouter, config: ConfigType): void =
maxBytes: config.maxImportPayloadBytes,
parse: false,
},
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: `${LIST_ITEM_URL}/_import`,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/patch_list_item_route.ts b/x-pack/plugins/lists/server/routes/patch_list_item_route.ts
index f706559dffdbd..d975e80079ab7 100644
--- a/x-pack/plugins/lists/server/routes/patch_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/patch_list_item_route.ts
@@ -17,7 +17,7 @@ export const patchListItemRoute = (router: IRouter): void => {
router.patch(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_ITEM_URL,
validate: {
@@ -27,9 +27,10 @@ export const patchListItemRoute = (router: IRouter): void => {
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);
try {
- const { value, id, meta } = request.body;
+ const { value, id, meta, _version } = request.body;
const lists = getListClient(context);
const listItem = await lists.updateListItem({
+ _version,
id,
meta,
value,
diff --git a/x-pack/plugins/lists/server/routes/patch_list_route.ts b/x-pack/plugins/lists/server/routes/patch_list_route.ts
index 3a0d8714a14cd..681581c6ff6bd 100644
--- a/x-pack/plugins/lists/server/routes/patch_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/patch_list_route.ts
@@ -17,7 +17,7 @@ export const patchListRoute = (router: IRouter): void => {
router.patch(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_URL,
validate: {
@@ -27,9 +27,9 @@ export const patchListRoute = (router: IRouter): void => {
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);
try {
- const { name, description, id, meta } = request.body;
+ const { name, description, id, meta, _version } = request.body;
const lists = getListClient(context);
- const list = await lists.updateList({ description, id, meta, name });
+ const list = await lists.updateList({ _version, description, id, meta, name });
if (list == null) {
return siemResponse.error({
body: `list id: "${id}" found found`,
diff --git a/x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts b/x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts
index 5e7ed901bf0cb..fd932746ce990 100644
--- a/x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_endpoint_list_item_route.ts
@@ -21,7 +21,7 @@ export const readEndpointListItemRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: ENDPOINT_LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts
index c4e969b27fcf4..fe8256fbda5cd 100644
--- a/x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_exception_list_item_route.ts
@@ -21,7 +21,7 @@ export const readExceptionListItemRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: EXCEPTION_LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/read_exception_list_route.ts b/x-pack/plugins/lists/server/routes/read_exception_list_route.ts
index 6cb91c10aea55..0512876d298d4 100644
--- a/x-pack/plugins/lists/server/routes/read_exception_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_exception_list_route.ts
@@ -21,7 +21,7 @@ export const readExceptionListRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: EXCEPTION_LIST_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/read_list_index_route.ts b/x-pack/plugins/lists/server/routes/read_list_index_route.ts
index 4664bed3e7a8b..87a4d85e0d254 100644
--- a/x-pack/plugins/lists/server/routes/read_list_index_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_list_index_route.ts
@@ -17,7 +17,7 @@ export const readListIndexRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: LIST_INDEX,
validate: false,
diff --git a/x-pack/plugins/lists/server/routes/read_list_item_route.ts b/x-pack/plugins/lists/server/routes/read_list_item_route.ts
index 24011d3b50d27..b7cf2b9f7123b 100644
--- a/x-pack/plugins/lists/server/routes/read_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_list_item_route.ts
@@ -17,7 +17,7 @@ export const readListItemRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: LIST_ITEM_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/read_list_route.ts b/x-pack/plugins/lists/server/routes/read_list_route.ts
index 34924b70fd4df..4bce09ecd3bde 100644
--- a/x-pack/plugins/lists/server/routes/read_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_list_route.ts
@@ -17,7 +17,7 @@ export const readListRoute = (router: IRouter): void => {
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: LIST_URL,
validate: {
diff --git a/x-pack/plugins/lists/server/routes/read_privileges_route.ts b/x-pack/plugins/lists/server/routes/read_privileges_route.ts
index 892b6406a28ec..a4ec878613608 100644
--- a/x-pack/plugins/lists/server/routes/read_privileges_route.ts
+++ b/x-pack/plugins/lists/server/routes/read_privileges_route.ts
@@ -20,7 +20,7 @@ export const readPrivilegesRoute = (
router.get(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-read'],
},
path: LIST_PRIVILEGES_URL,
validate: false,
diff --git a/x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts b/x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts
index 1ecf4e8a9765d..f717dc0fb3392 100644
--- a/x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/update_endpoint_list_item_route.ts
@@ -21,7 +21,7 @@ export const updateEndpointListItemRoute = (router: IRouter): void => {
router.put(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: ENDPOINT_LIST_ITEM_URL,
validate: {
@@ -41,6 +41,7 @@ export const updateEndpointListItemRoute = (router: IRouter): void => {
meta,
type,
_tags,
+ _version,
comments,
entries,
item_id: itemId,
@@ -49,6 +50,7 @@ export const updateEndpointListItemRoute = (router: IRouter): void => {
const exceptionLists = getExceptionListClient(context);
const exceptionListItem = await exceptionLists.updateEndpointListItem({
_tags,
+ _version,
comments,
description,
entries,
diff --git a/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts b/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts
index f6c7bcebedc13..293435b3f6202 100644
--- a/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/update_exception_list_item_route.ts
@@ -21,7 +21,7 @@ export const updateExceptionListItemRoute = (router: IRouter): void => {
router.put(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: EXCEPTION_LIST_ITEM_URL,
validate: {
@@ -41,6 +41,7 @@ export const updateExceptionListItemRoute = (router: IRouter): void => {
meta,
type,
_tags,
+ _version,
comments,
entries,
item_id: itemId,
@@ -50,6 +51,7 @@ export const updateExceptionListItemRoute = (router: IRouter): void => {
const exceptionLists = getExceptionListClient(context);
const exceptionListItem = await exceptionLists.updateExceptionListItem({
_tags,
+ _version,
comments,
description,
entries,
diff --git a/x-pack/plugins/lists/server/routes/update_exception_list_route.ts b/x-pack/plugins/lists/server/routes/update_exception_list_route.ts
index cff78614d05ba..403a9f6db934f 100644
--- a/x-pack/plugins/lists/server/routes/update_exception_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/update_exception_list_route.ts
@@ -21,7 +21,7 @@ export const updateExceptionListRoute = (router: IRouter): void => {
router.put(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: EXCEPTION_LIST_URL,
validate: {
@@ -36,6 +36,7 @@ export const updateExceptionListRoute = (router: IRouter): void => {
try {
const {
_tags,
+ _version,
tags,
name,
description,
@@ -54,6 +55,7 @@ export const updateExceptionListRoute = (router: IRouter): void => {
} else {
const list = await exceptionLists.updateExceptionList({
_tags,
+ _version,
description,
id,
listId,
diff --git a/x-pack/plugins/lists/server/routes/update_list_item_route.ts b/x-pack/plugins/lists/server/routes/update_list_item_route.ts
index 3e231e319104b..d479bc63b64bd 100644
--- a/x-pack/plugins/lists/server/routes/update_list_item_route.ts
+++ b/x-pack/plugins/lists/server/routes/update_list_item_route.ts
@@ -17,7 +17,7 @@ export const updateListItemRoute = (router: IRouter): void => {
router.put(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_ITEM_URL,
validate: {
@@ -27,9 +27,10 @@ export const updateListItemRoute = (router: IRouter): void => {
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);
try {
- const { value, id, meta } = request.body;
+ const { value, id, meta, _version } = request.body;
const lists = getListClient(context);
const listItem = await lists.updateListItem({
+ _version,
id,
meta,
value,
diff --git a/x-pack/plugins/lists/server/routes/update_list_route.ts b/x-pack/plugins/lists/server/routes/update_list_route.ts
index a6d9f8329c7c8..78aed23db13fc 100644
--- a/x-pack/plugins/lists/server/routes/update_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/update_list_route.ts
@@ -17,7 +17,7 @@ export const updateListRoute = (router: IRouter): void => {
router.put(
{
options: {
- tags: ['access:lists'],
+ tags: ['access:lists-all'],
},
path: LIST_URL,
validate: {
@@ -27,9 +27,9 @@ export const updateListRoute = (router: IRouter): void => {
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);
try {
- const { name, description, id, meta } = request.body;
+ const { name, description, id, meta, _version } = request.body;
const lists = getListClient(context);
- const list = await lists.updateList({ description, id, meta, name });
+ const list = await lists.updateList({ _version, description, id, meta, name });
if (list == null) {
return siemResponse.error({
body: `list id: "${id}" found found`,
diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update.json b/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update.json
index a7fbe1ea48c02..8d07b29d7b428 100644
--- a/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update.json
+++ b/x-pack/plugins/lists/server/scripts/exception_lists/updates/simple_update.json
@@ -1,5 +1,5 @@
{
- "list_id": "endpoint_list",
+ "list_id": "simple_list",
"_tags": ["endpoint", "process", "malware", "os:linux"],
"tags": ["user added string for a tag", "malware"],
"type": "endpoint",
diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts
index 5c9607e2d956d..08b1f517036a9 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.ts
@@ -131,6 +131,7 @@ export class ExceptionListClient {
*/
public updateEndpointListItem = async ({
_tags,
+ _version,
comments,
description,
entries,
@@ -145,6 +146,7 @@ export class ExceptionListClient {
await this.createEndpointList();
return updateExceptionListItem({
_tags,
+ _version,
comments,
description,
entries,
@@ -198,6 +200,7 @@ export class ExceptionListClient {
public updateExceptionList = async ({
_tags,
+ _version,
id,
description,
listId,
@@ -210,6 +213,7 @@ export class ExceptionListClient {
const { savedObjectsClient, user } = this;
return updateExceptionList({
_tags,
+ _version,
description,
id,
listId,
@@ -270,6 +274,7 @@ export class ExceptionListClient {
public updateExceptionListItem = async ({
_tags,
+ _version,
comments,
description,
entries,
@@ -284,6 +289,7 @@ export class ExceptionListClient {
const { savedObjectsClient, user } = this;
return updateExceptionListItem({
_tags,
+ _version,
comments,
description,
entries,
diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts
index 89f8310281648..b972b6564bb8a 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client_types.ts
@@ -38,6 +38,7 @@ import {
UpdateCommentsArray,
_Tags,
_TagsOrUndefined,
+ _VersionOrUndefined,
} from '../../../common/schemas';
export interface ConstructorOptions {
@@ -64,6 +65,7 @@ export interface CreateExceptionListOptions {
export interface UpdateExceptionListOptions {
_tags: _TagsOrUndefined;
+ _version: _VersionOrUndefined;
id: IdOrUndefined;
listId: ListIdOrUndefined;
namespaceType: NamespaceType;
@@ -130,6 +132,7 @@ export interface CreateEndpointListItemOptions {
export interface UpdateExceptionListItemOptions {
_tags: _TagsOrUndefined;
+ _version: _VersionOrUndefined;
comments: UpdateCommentsArray;
entries: EntriesArrayOrUndefined;
id: IdOrUndefined;
@@ -144,6 +147,7 @@ export interface UpdateExceptionListItemOptions {
export interface UpdateEndpointListItemOptions {
_tags: _TagsOrUndefined;
+ _version: _VersionOrUndefined;
comments: UpdateCommentsArray;
entries: EntriesArrayOrUndefined;
id: IdOrUndefined;
diff --git a/x-pack/plugins/lists/server/services/exception_lists/update_exception_list.ts b/x-pack/plugins/lists/server/services/exception_lists/update_exception_list.ts
index a739366c67331..99c42e56f4888 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/update_exception_list.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/update_exception_list.ts
@@ -18,6 +18,7 @@ import {
NamespaceType,
TagsOrUndefined,
_TagsOrUndefined,
+ _VersionOrUndefined,
} from '../../../common/schemas';
import { getSavedObjectType, transformSavedObjectUpdateToExceptionList } from './utils';
@@ -26,6 +27,7 @@ import { getExceptionList } from './get_exception_list';
interface UpdateExceptionListOptions {
id: IdOrUndefined;
_tags: _TagsOrUndefined;
+ _version: _VersionOrUndefined;
name: NameOrUndefined;
description: DescriptionOrUndefined;
savedObjectsClient: SavedObjectsClientContract;
@@ -40,6 +42,7 @@ interface UpdateExceptionListOptions {
export const updateExceptionList = async ({
_tags,
+ _version,
id,
savedObjectsClient,
namespaceType,
@@ -67,6 +70,9 @@ export const updateExceptionList = async ({
tags,
type,
updated_by: user,
+ },
+ {
+ version: _version,
}
);
return transformSavedObjectUpdateToExceptionList({ exceptionList, savedObject });
diff --git a/x-pack/plugins/lists/server/services/exception_lists/update_exception_list_item.ts b/x-pack/plugins/lists/server/services/exception_lists/update_exception_list_item.ts
index a5ed1e38df374..f26dd7e18dd5c 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/update_exception_list_item.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/update_exception_list_item.ts
@@ -20,6 +20,7 @@ import {
TagsOrUndefined,
UpdateCommentsArrayOrUndefined,
_TagsOrUndefined,
+ _VersionOrUndefined,
} from '../../../common/schemas';
import {
@@ -33,6 +34,7 @@ interface UpdateExceptionListItemOptions {
id: IdOrUndefined;
comments: UpdateCommentsArrayOrUndefined;
_tags: _TagsOrUndefined;
+ _version: _VersionOrUndefined;
name: NameOrUndefined;
description: DescriptionOrUndefined;
entries: EntriesArrayOrUndefined;
@@ -48,6 +50,7 @@ interface UpdateExceptionListItemOptions {
export const updateExceptionListItem = async ({
_tags,
+ _version,
comments,
entries,
id,
@@ -89,6 +92,9 @@ export const updateExceptionListItem = async ({
tags,
type,
updated_by: user,
+ },
+ {
+ version: _version,
}
);
return transformSavedObjectUpdateToExceptionListItem({
diff --git a/x-pack/plugins/lists/server/services/exception_lists/utils.ts b/x-pack/plugins/lists/server/services/exception_lists/utils.ts
index ded39933fe9d8..d5e1965efcc89 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/utils.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/utils.ts
@@ -72,6 +72,7 @@ export const transformSavedObjectToExceptionList = ({
}): ExceptionListSchema => {
const dateNow = new Date().toISOString();
const {
+ version: _version,
attributes: {
_tags,
created_at,
@@ -93,6 +94,7 @@ export const transformSavedObjectToExceptionList = ({
// TODO: Do a throw if after the decode this is not the correct "list_type: list"
return {
_tags,
+ _version,
created_at,
created_by,
description,
@@ -118,6 +120,7 @@ export const transformSavedObjectUpdateToExceptionList = ({
}): ExceptionListSchema => {
const dateNow = new Date().toISOString();
const {
+ version: _version,
attributes: { _tags, description, meta, name, tags, type, updated_by: updatedBy },
id,
updated_at: updatedAt,
@@ -127,6 +130,7 @@ export const transformSavedObjectUpdateToExceptionList = ({
// TODO: Do a throw if after the decode this is not the correct "list_type: list"
return {
_tags: _tags ?? exceptionList._tags,
+ _version,
created_at: exceptionList.created_at,
created_by: exceptionList.created_by,
description: description ?? exceptionList.description,
@@ -150,6 +154,7 @@ export const transformSavedObjectToExceptionListItem = ({
}): ExceptionListItemSchema => {
const dateNow = new Date().toISOString();
const {
+ version: _version,
attributes: {
_tags,
comments,
@@ -174,6 +179,7 @@ export const transformSavedObjectToExceptionListItem = ({
// TODO: Do a throw if item_id or entries is not defined.
return {
_tags,
+ _version,
comments: comments ?? [],
created_at,
created_by,
@@ -202,6 +208,7 @@ export const transformSavedObjectUpdateToExceptionListItem = ({
}): ExceptionListItemSchema => {
const dateNow = new Date().toISOString();
const {
+ version: _version,
attributes: {
_tags,
comments,
@@ -223,6 +230,7 @@ export const transformSavedObjectUpdateToExceptionListItem = ({
// defaulting
return {
_tags: _tags ?? exceptionListItem._tags,
+ _version,
comments: comments ?? exceptionListItem.comments,
created_at: exceptionListItem.created_at,
created_by: exceptionListItem.created_by,
diff --git a/x-pack/plugins/lists/server/services/items/create_list_item.ts b/x-pack/plugins/lists/server/services/items/create_list_item.ts
index aa17fc00b25c6..5332e2f6c7f4e 100644
--- a/x-pack/plugins/lists/server/services/items/create_list_item.ts
+++ b/x-pack/plugins/lists/server/services/items/create_list_item.ts
@@ -18,6 +18,7 @@ import {
Type,
} from '../../../common/schemas';
import { transformListItemToElasticQuery } from '../utils';
+import { encodeHitVersion } from '../utils/encode_hit_version';
export interface CreateListItemOptions {
deserializer: DeserializerOrUndefined;
@@ -75,6 +76,7 @@ export const createListItem = async ({
});
return {
+ _version: encodeHitVersion(response),
id: response._id,
type,
value,
diff --git a/x-pack/plugins/lists/server/services/items/find_list_item.ts b/x-pack/plugins/lists/server/services/items/find_list_item.ts
index 93fa682631b06..a997b10004e76 100644
--- a/x-pack/plugins/lists/server/services/items/find_list_item.ts
+++ b/x-pack/plugins/lists/server/services/items/find_list_item.ts
@@ -5,6 +5,7 @@
*/
import { LegacyAPICaller } from 'kibana/server';
+import { SearchResponse } from 'elasticsearch';
import {
Filter,
@@ -82,7 +83,10 @@ export const findListItem = async ({
});
if (scroll.validSearchAfterFound) {
- const response = await callCluster('search', {
+ // Note: This typing of response = await callCluster>
+ // is because when you pass in seq_no_primary_term: true it does a "fall through" type and you have
+ // to explicitly define the type .
+ const response = await callCluster>('search', {
body: {
query,
search_after: scroll.searchAfter,
@@ -90,6 +94,7 @@ export const findListItem = async ({
},
ignoreUnavailable: true,
index: listItemIndex,
+ seq_no_primary_term: true,
size: perPage,
});
return {
diff --git a/x-pack/plugins/lists/server/services/items/get_list_item.ts b/x-pack/plugins/lists/server/services/items/get_list_item.ts
index 6f2a7ad63a973..ad9ae8763fe94 100644
--- a/x-pack/plugins/lists/server/services/items/get_list_item.ts
+++ b/x-pack/plugins/lists/server/services/items/get_list_item.ts
@@ -5,6 +5,7 @@
*/
import { LegacyAPICaller } from 'kibana/server';
+import { SearchResponse } from 'elasticsearch';
import { Id, ListItemSchema, SearchEsListItemSchema } from '../../../common/schemas';
import { transformElasticToListItem } from '../utils';
@@ -21,7 +22,10 @@ export const getListItem = async ({
callCluster,
listItemIndex,
}: GetListItemOptions): Promise => {
- const listItemES = await callCluster('search', {
+ // Note: This typing of response = await callCluster>
+ // is because when you pass in seq_no_primary_term: true it does a "fall through" type and you have
+ // to explicitly define the type