From 312df5546c2c752f4159772207e55aa1575b535d Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 25 Oct 2018 10:32:50 -0700 Subject: [PATCH 1/7] [DOCS] Updates Elasticsearch monitoring tasks (#34339) --- .../configuring-metricbeat.asciidoc | 195 ++++++++++++++++++ .../configuring-monitoring.asciidoc | 40 +++- .../monitoring/images/metricbeat.png | Bin 0 -> 80106 bytes docs/reference/monitoring/indices.asciidoc | 2 +- .../settings/monitoring-settings.asciidoc | 24 +-- 5 files changed, 231 insertions(+), 30 deletions(-) create mode 100644 docs/reference/monitoring/configuring-metricbeat.asciidoc create mode 100644 docs/reference/monitoring/images/metricbeat.png diff --git a/docs/reference/monitoring/configuring-metricbeat.asciidoc b/docs/reference/monitoring/configuring-metricbeat.asciidoc new file mode 100644 index 00000000000..3d4a37861f1 --- /dev/null +++ b/docs/reference/monitoring/configuring-metricbeat.asciidoc @@ -0,0 +1,195 @@ +[role="xpack"] +[testenv="gold"] +[[configuring-metricbeat]] +=== Monitoring {es} with {metricbeat} + +beta[] In 6.5 and later, you can use {metricbeat} to collect data about {es} +and ship it to the monitoring cluster, rather than routing it through exporters +as described in <>. + +image::monitoring/images/metricbeat.png[Example monitoring architecture] + +To learn about monitoring in general, see +{stack-ov}/xpack-monitoring.html[Monitoring the {stack}]. + +. Enable the collection of monitoring data. Set +`xpack.monitoring.collection.enabled` to `true` on the production cluster. + ++ +-- +For example, you can use the following APIs to review and change this setting: + +[source,js] +---------------------------------- +GET _cluster/settings + +PUT _cluster/settings +{ + "persistent": { + "xpack.monitoring.collection.enabled": true + } +} +---------------------------------- +// CONSOLE + +For more information, see <> and <>. +-- + +. Disable the default collection of {es} monitoring metrics. Set +`xpack.monitoring.elasticsearch.collection.enabled` to `false` on the production +cluster. + ++ +-- +For example, you can use the following API to change this setting: + +[source,js] +---------------------------------- +PUT _cluster/settings +{ + "persistent": { + "xpack.monitoring.elasticsearch.collection.enabled": false + } +} +---------------------------------- +// CONSOLE + +Leave `xpack.monitoring.enabled` set to its default value (`true`). +-- + +. On each {es} node in the production cluster: + +.. {metricbeat-ref}/metricbeat-installation.html[Install {metricbeat}]. + +.. Enable the {es} module in {metricbeat}. + ++ +-- +For example, to enable the default configuration in the `modules.d` directory, +run the following command: + +["source","sh",subs="attributes,callouts"] +---------------------------------------------------------------------- +metricbeat modules enable elasticsearch +---------------------------------------------------------------------- + +For more information, see +{metricbeat-ref}/configuration-metricbeat.html[Specify which modules to run] and +{metricbeat-ref}/metricbeat-module-elasticsearch.html[{es} module]. +-- + +.. Configure the {es} module in {metricbeat}. + ++ +-- +You must specify the following settings in the `modules.d/elasticsearch.yml` file: + +[source,yaml] +---------------------------------- +- module: elasticsearch + metricsets: + - ccr + - cluster_stats + - index + - index_recovery + - index_summary + - ml_job + - node_stats + - shard + period: 10s + hosts: ["http://localhost:9200"] <1> + xpack.enabled: true +---------------------------------- +<1> This setting identifies the host and port number that are used to access {es}. +-- + +.. If {security} is enabled, you must also provide a user ID and password so that +{metricbeat} can collect metrics successfully. + +... Create or identify a user that you want to use to collect the metrics. ++ +-- +TIP: There is a `remote_monitoring_user` built-in user that grants the privileges +necessary for {metricbeat} to monitor {stack} products. See +{stack-ov}/built-in-users.html[Built-in users]. + +Alternatively, you can choose a different user and give them the +`remote_monitoring_collector` {stack-ov}/built-in-roles.html[built-in role]. +-- + +... Add the `username` and `password` settings to the {es} module configuration +file. ++ +-- +For example, add the following settings in the `modules.d/kibana.yml` file: + +[source,yaml] +---------------------------------- +- module: elasticsearch + ... + username: remote_monitoring_user + password: YOUR_PASSWORD +---------------------------------- +-- + +.. If you configured {es} to use <>, +you must access it via HTTPS. For example, use a `hosts` setting like +`https://localhost:9200` in the `modules.d/elasticsearch.yml` file. + +.. Identify where to send the monitoring data. + ++ +-- +TIP: In production environments, we strongly recommend using a separate cluster +(referred to as the _monitoring cluster_) to store the data. Using a separate +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. + +For example, specify the {es} output information in the {metricbeat} +configuration file (`metricbeat.yml`): + +[source,yaml] +---------------------------------- +output.elasticsearch: + hosts: ["http://es-mon-1:9200", "http://es-mon2:9200"] <1> +---------------------------------- +<1> In this example, the data is stored on a monitoring cluster with nodes +`es-mon-1` and `es-mon-2`. + +For more information about these configuration options, see +{metricbeat-ref}/elasticsearch-output.html[Configure the {es} output]. +-- + +.. If {security} is enabled on the monitoring cluster, you must provide a valid +user ID and password so that {metricbeat} can send metrics successfully. + +... Create or identify a user that you want to use to send the metrics. ++ +-- +TIP: There is a `remote_monitoring_user` built-in user that grants the privileges +necessary for {metricbeat} to monitor {stack} products. See +{stack-ov}/built-in-users.html[Built-in users]. + +Alternatively, you can choose a different user and give them the +`remote_monitoring_agent` {stack-ov}/built-in-roles.html[built-in role]. +-- + +... Add the `username` and `password` settings to the {es} output information in +the {metricbeat} configuration file (`metricbeat.yml`): ++ +-- +[source,yaml] +---------------------------------- +output.elasticsearch: + ... + username: remote_monitoring_user + password: YOUR_PASSWORD +---------------------------------- +-- + +.. If you configured the monitoring cluster to use +<>, you must access it via +HTTPS. For example, use a `hosts` setting like `https://es-mon-1:9200` in the +`metricbeat.yml` file. + +. <>. + +. {metricbeat-ref}/metricbeat-starting.html[Start {metricbeat}]. + +. {kibana-ref}/monitoring-data.html[View the monitoring data in {kib}]. diff --git a/docs/reference/monitoring/configuring-monitoring.asciidoc b/docs/reference/monitoring/configuring-monitoring.asciidoc index 6708b791036..81a9cce4f12 100644 --- a/docs/reference/monitoring/configuring-monitoring.asciidoc +++ b/docs/reference/monitoring/configuring-monitoring.asciidoc @@ -6,18 +6,27 @@ Configuring monitoring ++++ -By default, {monitoring} is enabled but data collection is disabled. Advanced -monitoring settings enable you to control how frequently data is collected, -configure timeouts, and set the retention period for locally-stored monitoring -indices. You can also adjust how monitoring data is displayed. +If you enable the collection of monitoring data in your cluster, you can +optionally collect metrics about {es}. By default, {monitoring} is enabled but +data collection is disabled. + +The following method involves sending the metrics to the monitoring cluster by +using exporters. For an alternative method, see <>. + +Advanced monitoring settings enable you to control how frequently data is +collected, configure timeouts, and set the retention period for locally-stored +monitoring indices. You can also adjust how monitoring data is displayed. + +To learn about monitoring in general, see +{stack-ov}/xpack-monitoring.html[Monitoring the {stack}]. . To collect monitoring data about your {es} cluster: .. Verify that the `xpack.monitoring.enabled`, `xpack.monitoring.collection.enabled`, and `xpack.monitoring.elasticsearch.collection.enabled` settings are `true` on each -node in the cluster. By default xpack.monitoring.collection.enabled is disabled -(`false`), and that overrides xpack.monitoring.elasticsearch.collection.enabled, +node in the cluster. By default `xpack.monitoring.collection.enabled` is disabled +(`false`), and that overrides `xpack.monitoring.elasticsearch.collection.enabled`, which defaults to being enabled (`true`). Both settings can be set dynamically at runtime. For more information, see <>. @@ -69,8 +78,9 @@ see {stack-ov}/how-monitoring-works.html[How Monitoring Works]. a dedicated monitoring cluster: .. Create a user on the monitoring cluster that has the -{xpack-ref}/built-in-roles.html#built-in-roles-remote-monitoring-agent[`remote_monitoring_agent` built-in role]. For example, the following request -creates a `remote_monitor` user that has the `remote_monitoring_agent` role: +{stack-ov}/built-in-roles.html#built-in-roles-remote-monitoring-agent[`remote_monitoring_agent` built-in role]. +For example, the following request creates a `remote_monitor` user that has the +`remote_monitoring_agent` role: + -- [source, sh] @@ -87,12 +97,17 @@ POST /_xpack/security/user/remote_monitor -- .. On each node in the cluster that is being monitored, configure the `http` -exporter to use the appropriate credentials when data is shipped to the monitoring cluster. +exporter to use the appropriate credentials when data is shipped to the +monitoring cluster. + -- -If SSL/TLS is enabled on the monitoring cluster, you must use the HTTPS protocol in the `host` setting. You must also include the CA certificate in each node's trusted certificates in order to verify the identities of the nodes in the monitoring cluster. +If SSL/TLS is enabled on the monitoring cluster, you must use the HTTPS protocol +in the `host` setting. You must also include the CA certificate in each node's +trusted certificates in order to verify the identities of the nodes in the +monitoring cluster. -The following example specifies the location of the PEM encoded certificate with the `certificate_authorities` setting: +The following example specifies the location of the PEM encoded certificate with +the `certificate_authorities` setting: [source,yaml] -------------------------------------------------- @@ -144,5 +159,8 @@ stored, that is to say the monitoring cluster. To grant all of the necessary per . Optional: <>. +. {kibana-ref}/monitoring-data.html[View the monitoring data in {kib}]. + +include::configuring-metricbeat.asciidoc[] include::indices.asciidoc[] include::{es-repo-dir}/settings/monitoring-settings.asciidoc[] \ No newline at end of file diff --git a/docs/reference/monitoring/images/metricbeat.png b/docs/reference/monitoring/images/metricbeat.png new file mode 100644 index 0000000000000000000000000000000000000000..bf6434dc4b40c00f65c41fb50d1050cf7c657be4 GIT binary patch literal 80106 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

=|XdNy9y;C5oLyou;4x?e;^5_ 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 are used to configure the indices that store the monitoring data collected from a cluster. diff --git a/docs/reference/settings/monitoring-settings.asciidoc b/docs/reference/settings/monitoring-settings.asciidoc index a039084412c..92c51772720 100644 --- a/docs/reference/settings/monitoring-settings.asciidoc +++ b/docs/reference/settings/monitoring-settings.asciidoc @@ -1,8 +1,8 @@ [role="xpack"] [[monitoring-settings]] -=== Monitoring Settings in Elasticsearch +=== Monitoring settings in Elasticsearch ++++ -Monitoring Settings +Monitoring settings ++++ By default, monitoring is enabled but data collection is disabled. To enable @@ -43,17 +43,14 @@ to `true`. Its default value is `false`. The `xpack.monitoring.collection` settings control how data is collected from your Elasticsearch nodes. -`xpack.monitoring.collection.enabled`:: +`xpack.monitoring.collection.enabled`:: (<>) added[6.3.0] Set to `true` to enable the collection of monitoring data. When this setting is `false` (default), {es} monitoring data is not collected and all monitoring data from other sources such as {kib}, Beats, and Logstash is ignored. -+ -You can update this setting through the -<>. -`xpack.monitoring.collection.interval`:: +`xpack.monitoring.collection.interval`:: (<>) Setting to `-1` to disable data collection is no longer supported beginning with 7.0.0. deprecated[6.3.0, Use `xpack.monitoring.collection.enabled` set to @@ -62,35 +59,26 @@ Setting to `-1` to disable data collection is no longer supported beginning with Controls how often data samples are collected. Defaults to `10s`. If you modify the collection interval, set the `xpack.monitoring.min_interval_seconds` option in `kibana.yml` to the same value. -+ -You can update this setting through the -<>. -`xpack.monitoring.elasticsearch.collection.enabled`:: +`xpack.monitoring.elasticsearch.collection.enabled`:: (<>) Controls whether statistics about your {es} cluster should be collected. Defaults to `true`. This is different from xpack.monitoring.collection.enabled, which allows you to enable or disable all monitoring collection. However, this setting simply disables the collection of Elasticsearch data while still allowing other data (e.g., Kibana, Logstash, Beats, or APM Server monitoring data) to pass through this cluster. -+ -You can update this setting through the -<>. `xpack.monitoring.collection.cluster.stats.timeout`:: Sets the timeout for collecting the cluster statistics. Defaults to `10s`. -`xpack.monitoring.collection.indices`:: +`xpack.monitoring.collection.indices`:: (<>) Controls which indices Monitoring collects data from. Defaults to all indices. Specify the index names as a comma-separated list, for example `test1,test2,test3`. Names can include wildcards, for example `test*`. You can explicitly include or exclude indices by prepending `+` to include the index, or `-` to exclude the index. For example, to include all indices that start with `test` except `test3`, you could specify `+test*,-test3`. -+ -You can update this setting through the -<>. `xpack.monitoring.collection.index.stats.timeout`:: From cf9aff954ef916aaf1bddea362bcbb91466e60a1 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Thu, 25 Oct 2018 13:37:49 -0600 Subject: [PATCH 2/7] Reduce channels in AbstractSimpleTransportTestCase (#34863) This is related to #30876. The AbstractSimpleTransportTestCase initiates many tcp connections. There are normally over 1,000 connections in TIME_WAIT at the end of the test. This is because every test opens at least two different transports that connect to each other with 13 channel connection profiles. This commit modifies the default connection profile used by this test to 6. One connection for each type, except for REG which gets 2 connections. --- .../netty4/SimpleNetty4TransportTests.java | 2 +- .../nio/SimpleNioTransportTests.java | 2 +- .../transport/ConnectionManager.java | 21 +-------------- .../transport/ConnectionProfile.java | 27 +++++++++++++++++++ .../transport/ConnectionManagerTests.java | 10 +++---- .../AbstractSimpleTransportTestCase.java | 24 +++++++++++++---- .../transport/MockTcpTransportTests.java | 2 +- .../nio/SimpleMockNioTransportTests.java | 2 +- ...stractSimpleSecurityTransportTestCase.java | 3 +-- ...pleSecurityNetty4ServerTransportTests.java | 2 +- .../nio/SimpleSecurityNioTransportTests.java | 2 +- 11 files changed, 59 insertions(+), 38 deletions(-) diff --git a/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java b/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java index 4e63727024f..e7faac8ae01 100644 --- a/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java +++ b/modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/SimpleNetty4TransportTests.java @@ -73,7 +73,7 @@ public class SimpleNetty4TransportTests extends AbstractSimpleTransportTestCase } }; MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, Collections.emptySet()); + MockTransportService.createNewService(settings, transport, version, threadPool, clusterSettings, Collections.emptySet()); mockTransportService.start(); return mockTransportService; } diff --git a/plugins/transport-nio/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java b/plugins/transport-nio/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java index 8f6d78b481d..33d40b9f735 100644 --- a/plugins/transport-nio/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java +++ b/plugins/transport-nio/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java @@ -77,7 +77,7 @@ public class SimpleNioTransportTests extends AbstractSimpleTransportTestCase { } }; MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, Collections.emptySet()); + MockTransportService.createNewService(settings, transport, version, threadPool, clusterSettings, Collections.emptySet()); mockTransportService.start(); return mockTransportService; } diff --git a/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java b/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java index 4e4d369330c..5f2635fac88 100644 --- a/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java +++ b/server/src/main/java/org/elasticsearch/transport/ConnectionManager.java @@ -67,7 +67,7 @@ public class ConnectionManager implements Closeable { private final DelegatingNodeConnectionListener connectionListener = new DelegatingNodeConnectionListener(); public ConnectionManager(Settings settings, Transport transport, ThreadPool threadPool) { - this(settings, transport, threadPool, buildDefaultConnectionProfile(settings)); + this(settings, transport, threadPool, ConnectionProfile.buildDefaultConnectionProfile(settings)); } public ConnectionManager(Settings settings, Transport transport, ThreadPool threadPool, ConnectionProfile defaultProfile) { @@ -323,23 +323,4 @@ public class ConnectionManager implements Closeable { } } } - - public static ConnectionProfile buildDefaultConnectionProfile(Settings settings) { - int connectionsPerNodeRecovery = TransportService.CONNECTIONS_PER_NODE_RECOVERY.get(settings); - int connectionsPerNodeBulk = TransportService.CONNECTIONS_PER_NODE_BULK.get(settings); - int connectionsPerNodeReg = TransportService.CONNECTIONS_PER_NODE_REG.get(settings); - int connectionsPerNodeState = TransportService.CONNECTIONS_PER_NODE_STATE.get(settings); - int connectionsPerNodePing = TransportService.CONNECTIONS_PER_NODE_PING.get(settings); - ConnectionProfile.Builder builder = new ConnectionProfile.Builder(); - builder.setConnectTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings)); - builder.setHandshakeTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings)); - builder.addConnections(connectionsPerNodeBulk, TransportRequestOptions.Type.BULK); - builder.addConnections(connectionsPerNodePing, TransportRequestOptions.Type.PING); - // if we are not master eligible we don't need a dedicated channel to publish the state - builder.addConnections(DiscoveryNode.isMasterNode(settings) ? connectionsPerNodeState : 0, TransportRequestOptions.Type.STATE); - // if we are not a data-node we don't need any dedicated channels for recovery - builder.addConnections(DiscoveryNode.isDataNode(settings) ? connectionsPerNodeRecovery : 0, TransportRequestOptions.Type.RECOVERY); - builder.addConnections(connectionsPerNodeReg, TransportRequestOptions.Type.REG); - return builder.build(); - } } diff --git a/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java b/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java index b9ed42ca00a..d6183655fa2 100644 --- a/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java +++ b/server/src/main/java/org/elasticsearch/transport/ConnectionProfile.java @@ -18,7 +18,9 @@ */ package org.elasticsearch.transport; +import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import java.util.ArrayList; @@ -91,6 +93,31 @@ public final class ConnectionProfile { } } + /** + * Builds a default connection profile based on the provided settings. + * + * @param settings to build the connection profile from + * @return the connection profile + */ + public static ConnectionProfile buildDefaultConnectionProfile(Settings settings) { + int connectionsPerNodeRecovery = TransportService.CONNECTIONS_PER_NODE_RECOVERY.get(settings); + int connectionsPerNodeBulk = TransportService.CONNECTIONS_PER_NODE_BULK.get(settings); + int connectionsPerNodeReg = TransportService.CONNECTIONS_PER_NODE_REG.get(settings); + int connectionsPerNodeState = TransportService.CONNECTIONS_PER_NODE_STATE.get(settings); + int connectionsPerNodePing = TransportService.CONNECTIONS_PER_NODE_PING.get(settings); + Builder builder = new Builder(); + builder.setConnectTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings)); + builder.setHandshakeTimeout(TransportService.TCP_CONNECT_TIMEOUT.get(settings)); + builder.addConnections(connectionsPerNodeBulk, TransportRequestOptions.Type.BULK); + builder.addConnections(connectionsPerNodePing, TransportRequestOptions.Type.PING); + // if we are not master eligible we don't need a dedicated channel to publish the state + builder.addConnections(DiscoveryNode.isMasterNode(settings) ? connectionsPerNodeState : 0, TransportRequestOptions.Type.STATE); + // if we are not a data-node we don't need any dedicated channels for recovery + builder.addConnections(DiscoveryNode.isDataNode(settings) ? connectionsPerNodeRecovery : 0, TransportRequestOptions.Type.RECOVERY); + builder.addConnections(connectionsPerNodeReg, TransportRequestOptions.Type.REG); + return builder.build(); + } + /** * A builder to build a new {@link ConnectionProfile} */ diff --git a/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java b/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java index bff5a2b122d..3dc9e0aece7 100644 --- a/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java +++ b/server/src/test/java/org/elasticsearch/transport/ConnectionManagerTests.java @@ -64,7 +64,7 @@ public class ConnectionManagerTests extends ESTestCase { } public void testConnectionProfileResolve() { - final ConnectionProfile defaultProfile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY); + final ConnectionProfile defaultProfile = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY); assertEquals(defaultProfile, ConnectionProfile.resolveConnectionProfile(null, defaultProfile)); final ConnectionProfile.Builder builder = new ConnectionProfile.Builder(); @@ -96,7 +96,7 @@ public class ConnectionManagerTests extends ESTestCase { } public void testDefaultConnectionProfile() { - ConnectionProfile profile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY); + ConnectionProfile profile = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY); assertEquals(13, profile.getNumConnections()); assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING)); assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG)); @@ -104,7 +104,7 @@ public class ConnectionManagerTests extends ESTestCase { assertEquals(2, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY)); assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK)); - profile = ConnectionManager.buildDefaultConnectionProfile(Settings.builder().put("node.master", false).build()); + profile = ConnectionProfile.buildDefaultConnectionProfile(Settings.builder().put("node.master", false).build()); assertEquals(12, profile.getNumConnections()); assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING)); assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG)); @@ -112,7 +112,7 @@ public class ConnectionManagerTests extends ESTestCase { assertEquals(2, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY)); assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK)); - profile = ConnectionManager.buildDefaultConnectionProfile(Settings.builder().put("node.data", false).build()); + profile = ConnectionProfile.buildDefaultConnectionProfile(Settings.builder().put("node.data", false).build()); assertEquals(11, profile.getNumConnections()); assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING)); assertEquals(6, profile.getNumConnectionsPerType(TransportRequestOptions.Type.REG)); @@ -120,7 +120,7 @@ public class ConnectionManagerTests extends ESTestCase { assertEquals(0, profile.getNumConnectionsPerType(TransportRequestOptions.Type.RECOVERY)); assertEquals(3, profile.getNumConnectionsPerType(TransportRequestOptions.Type.BULK)); - profile = ConnectionManager.buildDefaultConnectionProfile(Settings.builder().put("node.data", false) + profile = ConnectionProfile.buildDefaultConnectionProfile(Settings.builder().put("node.data", false) .put("node.master", false).build()); assertEquals(10, profile.getNumConnections()); assertEquals(1, profile.getNumConnectionsPerType(TransportRequestOptions.Type.PING)); diff --git a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java index 3b64f00084e..85a654c4cac 100644 --- a/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java @@ -116,7 +116,8 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase { protected abstract MockTransportService build(Settings settings, Version version, ClusterSettings clusterSettings, boolean doHandshake); protected int channelsPerNodeConnection() { - return 13; + // This is a customized profile for this test case. + return 6; } @Override @@ -125,9 +126,17 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase { super.setUp(); threadPool = new TestThreadPool(getClass().getName()); clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); - serviceA = buildService("TS_A", version0, clusterSettings); // this one supports dynamic tracer updates + Settings connectionSettings = Settings.builder() + .put(TransportService.CONNECTIONS_PER_NODE_RECOVERY.getKey(), 1) + .put(TransportService.CONNECTIONS_PER_NODE_BULK.getKey(), 1) + .put(TransportService.CONNECTIONS_PER_NODE_REG.getKey(), 2) + .put(TransportService.CONNECTIONS_PER_NODE_STATE.getKey(), 1) + .put(TransportService.CONNECTIONS_PER_NODE_PING.getKey(), 1) + .build(); + + serviceA = buildService("TS_A", version0, clusterSettings, connectionSettings); // this one supports dynamic tracer updates nodeA = serviceA.getLocalNode(); - serviceB = buildService("TS_B", version1, null); // this one doesn't support dynamic tracer updates + serviceB = buildService("TS_B", version1, null, connectionSettings); // this one doesn't support dynamic tracer updates nodeB = serviceB.getLocalNode(); // wait till all nodes are properly connected and the event has been sent, so tests in this class // will not get this callback called on the connections done in this setup @@ -174,7 +183,12 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase { } protected MockTransportService buildService(final String name, final Version version, ClusterSettings clusterSettings) { - return buildService(name, version, clusterSettings, Settings.EMPTY, true, true); + return buildService(name, version, clusterSettings, Settings.EMPTY); + } + + protected MockTransportService buildService(final String name, final Version version, ClusterSettings clusterSettings, + Settings settings) { + return buildService(name, version, clusterSettings, settings, true, true); } @Override @@ -1999,7 +2013,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase { assertEquals("handshake failed", exception.getCause().getMessage()); } - ConnectionProfile connectionProfile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY); + ConnectionProfile connectionProfile = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY); try (TransportService service = buildService("TS_TPC", Version.CURRENT, null); TcpTransport.NodeChannels connection = originalTransport.openConnection( new DiscoveryNode("TS_TPC", "TS_TPC", service.boundAddress().publishAddress(), emptyMap(), emptySet(), version0), diff --git a/test/framework/src/test/java/org/elasticsearch/transport/MockTcpTransportTests.java b/test/framework/src/test/java/org/elasticsearch/transport/MockTcpTransportTests.java index 4084d08b2e8..e8b5f38b88d 100644 --- a/test/framework/src/test/java/org/elasticsearch/transport/MockTcpTransportTests.java +++ b/test/framework/src/test/java/org/elasticsearch/transport/MockTcpTransportTests.java @@ -50,7 +50,7 @@ public class MockTcpTransportTests extends AbstractSimpleTransportTestCase { } }; MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, Collections.emptySet()); + MockTransportService.createNewService(settings, transport, version, threadPool, clusterSettings, Collections.emptySet()); mockTransportService.start(); return mockTransportService; } diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleMockNioTransportTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleMockNioTransportTests.java index bebe50752f4..10f089e855a 100644 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleMockNioTransportTests.java +++ b/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleMockNioTransportTests.java @@ -78,7 +78,7 @@ public class SimpleMockNioTransportTests extends AbstractSimpleTransportTestCase }; MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, Collections.emptySet()); + MockTransportService.createNewService(settings, transport, version, threadPool, clusterSettings, Collections.emptySet()); mockTransportService.start(); return mockTransportService; } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java index 2e1a423d5fd..077edf22c91 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/AbstractSimpleSecurityTransportTestCase.java @@ -21,7 +21,6 @@ import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.transport.AbstractSimpleTransportTestCase; import org.elasticsearch.transport.BindTransportException; import org.elasticsearch.transport.ConnectTransportException; -import org.elasticsearch.transport.ConnectionManager; import org.elasticsearch.transport.ConnectionProfile; import org.elasticsearch.transport.TcpTransport; import org.elasticsearch.transport.TransportRequestOptions; @@ -111,7 +110,7 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi assumeTrue("only tcp transport has a handshake method", serviceA.getOriginalTransport() instanceof TcpTransport); TcpTransport originalTransport = (TcpTransport) serviceA.getOriginalTransport(); - ConnectionProfile connectionProfile = ConnectionManager.buildDefaultConnectionProfile(Settings.EMPTY); + ConnectionProfile connectionProfile = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY); try (TransportService service = buildService("TS_TPC", Version.CURRENT, null); TcpTransport.NodeChannels connection = originalTransport.openConnection( new DiscoveryNode("TS_TPC", "TS_TPC", service.boundAddress().publishAddress(), emptyMap(), emptySet(), version0), diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java index 88895034df9..291b39f4b05 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SimpleSecurityNetty4ServerTransportTests.java @@ -93,7 +93,7 @@ public class SimpleSecurityNetty4ServerTransportTests extends AbstractSimpleSecu }; MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, + MockTransportService.createNewService(settings, transport, version, threadPool, clusterSettings, Collections.emptySet()); mockTransportService.start(); return mockTransportService; diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java index 5208d58d743..7fd4d8b5e03 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SimpleSecurityNioTransportTests.java @@ -55,7 +55,7 @@ public class SimpleSecurityNioTransportTests extends AbstractSimpleSecurityTrans }; MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, + MockTransportService.createNewService(settings, transport, version, threadPool, clusterSettings, Collections.emptySet()); mockTransportService.start(); return mockTransportService; From 06d743195091c96a45fc410759b788db60437f35 Mon Sep 17 00:00:00 2001 From: Marios Trivyzas Date: Thu, 25 Oct 2018 22:15:28 +0200 Subject: [PATCH 3/7] SQL: Return error with ORDER BY on non-grouped. (#34855) Previously, for some queries the validation for ORDER BY fields didn't kick in since a HAVING close or an ORDER BY with scalar function would add `Filter` and `Project` plans between the `OrderBy` and the `Aggregate`. Now the LogicalPlan tree beneath `OrderBy` is traversed and the ORDER BY fields are properly verified. Fixes: #34590 --- .../xpack/sql/analysis/analyzer/Verifier.java | 28 +++++++++++++------ .../analyzer/VerifierErrorMessagesTests.java | 10 +++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java index 32d57175114..c8834240c6c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java @@ -25,6 +25,7 @@ import org.elasticsearch.xpack.sql.plan.logical.Distinct; import org.elasticsearch.xpack.sql.plan.logical.Filter; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.plan.logical.OrderBy; +import org.elasticsearch.xpack.sql.plan.logical.Project; import org.elasticsearch.xpack.sql.tree.Node; import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.util.StringUtils; @@ -238,8 +239,17 @@ final class Verifier { Set groupingFailures, Map functions) { if (p instanceof OrderBy) { OrderBy o = (OrderBy) p; - if (o.child() instanceof Aggregate) { - Aggregate a = (Aggregate) o.child(); + LogicalPlan child = o.child(); + + if (child instanceof Project) { + child = ((Project) child).child(); + } + if (child instanceof Filter) { + child = ((Filter) child).child(); + } + + if (child instanceof Aggregate) { + Aggregate a = (Aggregate) child; Map> missing = new LinkedHashMap<>(); o.order().forEach(oe -> { @@ -253,7 +263,7 @@ final class Verifier { // take aliases declared inside the aggregates which point to the grouping (but are not included in there) // to correlate them to the order List groupingAndMatchingAggregatesAliases = new ArrayList<>(a.groupings()); - + a.aggregates().forEach(as -> { if (as instanceof Alias) { Alias al = (Alias) as; @@ -262,10 +272,13 @@ final class Verifier { } } }); - - // make sure to compare attributes directly - if (Expressions.anyMatch(groupingAndMatchingAggregatesAliases, - g -> e.semanticEquals(e instanceof Attribute ? Expressions.attribute(g) : g))) { + + // Make sure you can apply functions on top of the grouped by expressions in the ORDER BY: + // e.g.: if "GROUP BY f2(f1(field))" you can "ORDER BY f4(f3(f2(f1(field))))" + // + // Also, make sure to compare attributes directly + if (e.anyMatch(expression -> Expressions.anyMatch(groupingAndMatchingAggregatesAliases, + g -> expression.semanticEquals(expression instanceof Attribute ? Expressions.attribute(g) : g)))) { return; } @@ -288,7 +301,6 @@ final class Verifier { return true; } - private static boolean checkGroupByHaving(LogicalPlan p, Set localFailures, Set groupingFailures, Map functions) { if (p instanceof Filter) { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java index bc4f6a9f95c..e69b694968a 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java @@ -118,6 +118,11 @@ public class VerifierErrorMessagesTests extends ESTestCase { verify("SELECT MAX(int) FROM test GROUP BY text ORDER BY bool")); } + public void testGroupByOrderByNonGrouped_WithHaving() { + assertEquals("1:71: Cannot order by non-grouped column [bool], expected [text]", + verify("SELECT MAX(int) FROM test GROUP BY text HAVING MAX(int) > 10 ORDER BY bool")); + } + public void testGroupByOrderByAliasedInSelectAllowed() { LogicalPlan lp = accepted("SELECT text t FROM test GROUP BY text ORDER BY t"); assertNotNull(lp); @@ -128,6 +133,11 @@ public class VerifierErrorMessagesTests extends ESTestCase { verify("SELECT MAX(int) FROM test GROUP BY text ORDER BY YEAR(date)")); } + public void testGroupByOrderByScalarOverNonGrouped_WithHaving() { + assertEquals("1:71: Cannot order by non-grouped column [YEAR(date [UTC])], expected [text]", + verify("SELECT MAX(int) FROM test GROUP BY text HAVING MAX(int) > 10 ORDER BY YEAR(date)")); + } + public void testGroupByHavingNonGrouped() { assertEquals("1:48: Cannot filter by non-grouped column [int], expected [text]", verify("SELECT AVG(int) FROM test GROUP BY text HAVING int > 10")); From 59df6e868902330412107c6640dc2fdb4c511365 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Thu, 25 Oct 2018 14:02:30 -0400 Subject: [PATCH 4/7] Test: Lookup node versions on rest test start (#34657) This is a forward port of a change made to clean up backwards compatibility for the rollup cleanups. It makes the version of each node available very early on in test execution. The 6.x version of the change used those versions to control the cleanup backwards compatibility but that isn't needed in this branch. But having the versions around *is* useful. So this makes them available. Closes #34629 --- .../test/rest/ESRestTestCase.java | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java index 72299dab912..a540af459a1 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java @@ -26,6 +26,7 @@ import org.apache.http.message.BasicHeader; import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; +import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksAction; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; @@ -73,6 +74,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @@ -105,25 +107,13 @@ public abstract class ESRestTestCase extends ESTestCase { } /** - * Does the cluster being tested have xpack installed? + * Does any node in the cluster being tested have x-pack installed? */ public static boolean hasXPack() throws IOException { - RestClient client = adminClient(); - if (client == null) { + if (hasXPack == null) { throw new IllegalStateException("must be called inside of a rest test case test"); } - Map response = entityAsMap(client.performRequest(new Request("GET", "_nodes/plugins"))); - Map nodes = (Map) response.get("nodes"); - for (Map.Entry node : nodes.entrySet()) { - Map nodeInfo = (Map) node.getValue(); - for (Object module: (List) nodeInfo.get("modules")) { - Map moduleInfo = (Map) module; - if (moduleInfo.get("name").toString().startsWith("x-pack-")) { - return true; - } - } - } - return false; + return hasXPack; } private static List clusterHosts; @@ -136,12 +126,16 @@ public abstract class ESRestTestCase extends ESTestCase { * completes */ private static RestClient adminClient; + private static Boolean hasXPack; + private static TreeSet nodeVersions; @Before public void initClient() throws IOException { if (client == null) { assert adminClient == null; assert clusterHosts == null; + assert hasXPack == null; + assert nodeVersions == null; String cluster = System.getProperty("tests.rest.cluster"); if (cluster == null) { throw new RuntimeException("Must specify [tests.rest.cluster] system property with a comma delimited list of [host:port] " @@ -162,10 +156,27 @@ public abstract class ESRestTestCase extends ESTestCase { logger.info("initializing REST clients against {}", clusterHosts); client = buildClient(restClientSettings(), clusterHosts.toArray(new HttpHost[clusterHosts.size()])); adminClient = buildClient(restAdminSettings(), clusterHosts.toArray(new HttpHost[clusterHosts.size()])); + + hasXPack = false; + nodeVersions = new TreeSet<>(); + Map response = entityAsMap(adminClient.performRequest(new Request("GET", "_nodes/plugins"))); + Map nodes = (Map) response.get("nodes"); + for (Map.Entry node : nodes.entrySet()) { + Map nodeInfo = (Map) node.getValue(); + nodeVersions.add(Version.fromString(nodeInfo.get("version").toString())); + for (Object module: (List) nodeInfo.get("modules")) { + Map moduleInfo = (Map) module; + if (moduleInfo.get("name").toString().startsWith("x-pack-")) { + hasXPack = true; + } + } + } } assert client != null; assert adminClient != null; assert clusterHosts != null; + assert hasXPack != null; + assert nodeVersions != null; } /** @@ -195,6 +206,8 @@ public abstract class ESRestTestCase extends ESTestCase { clusterHosts = null; client = null; adminClient = null; + hasXPack = null; + nodeVersions = null; } } @@ -335,8 +348,6 @@ public abstract class ESRestTestCase extends ESTestCase { } private void wipeCluster() throws Exception { - boolean hasXPack = hasXPack(); - if (preserveIndicesUponCompletion() == false) { // wipe indices try { From 27c4d633406d1348d2b1c9f9177fdcbe28b707c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Campinas?= Date: Thu, 25 Oct 2018 22:48:06 +0200 Subject: [PATCH 5/7] document the search context is freed if the scroll is not extended (#34739) The `fetchPhaseShouldFreeContext` returns true when there is a scroll context but the scroll parameter is null, thus freeing the search context. https://github.com/elastic/elasticsearch/blob/183c32d4c39948e037a7fb44dccf31ab0d60d3c3/server/src/main/java/org/elasticsearch/search/SearchService.java#L491 --- docs/reference/search/request/scroll.asciidoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/reference/search/request/scroll.asciidoc b/docs/reference/search/request/scroll.asciidoc index c6a571f4b8f..4b96fe0e706 100644 --- a/docs/reference/search/request/scroll.asciidoc +++ b/docs/reference/search/request/scroll.asciidoc @@ -109,7 +109,9 @@ request) tells Elasticsearch how long it should keep the search context alive. Its value (e.g. `1m`, see <>) does not need to be long enough to process all data -- it just needs to be long enough to process the previous batch of results. Each `scroll` request (with the `scroll` parameter) sets a -new expiry time. +new expiry time. If a `scroll` request doesn't pass in the `scroll` +parameter, then the search context will be freed as part of _that_ `scroll` +request. Normally, the background merge process optimizes the index by merging together smaller segments to create new bigger segments, at From e27a0d5b0d2cccda65731c95d39d3942acec66d1 Mon Sep 17 00:00:00 2001 From: Senthil <34865595+senthilkumarmohan@users.noreply.github.com> Date: Thu, 25 Oct 2018 21:51:18 +0100 Subject: [PATCH 6/7] Docs: Align prose with snippet (#34839) Modified example text to include multiple index patterns used in the code --- docs/reference/indices/templates.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/indices/templates.asciidoc b/docs/reference/indices/templates.asciidoc index 051e78fc442..e70f461d3bc 100644 --- a/docs/reference/indices/templates.asciidoc +++ b/docs/reference/indices/templates.asciidoc @@ -46,9 +46,9 @@ PUT _template/template_1 NOTE: Index templates provide C-style /* */ block comments. Comments are allowed everywhere in the JSON document except before the initial opening curly bracket. -Defines a template named `template_1`, with a template pattern of `te*`. +Defines a template named `template_1`, with a template pattern of `te*` or `bar*`. The settings and mappings will be applied to any index name that matches -the `te*` pattern. +the `te*` or `bar*` pattern. It is also possible to include aliases in an index template as follows: From 3cde1356c1f2c9dca23be1ded4627093c0d3477c Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Thu, 25 Oct 2018 17:03:42 -0400 Subject: [PATCH 7/7] XContent: Check for bad parsers (#34561) Adds checks for misbehaving parsers. The checks aren't perfect at all but they are simple and fast enough that we can do them all the time so they'll catch most badly behaving parsers. Closes #34351 --- .../security/PutRoleMappingResponse.java | 9 ++-- .../common/xcontent/ObjectParser.java | 22 ++++++++++ .../common/xcontent/ObjectParserTests.java | 44 +++++++++++++++++++ 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java index 04cdb14163e..00039f1486e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleMappingResponse.java @@ -64,11 +64,10 @@ public final class PutRoleMappingResponse { private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( "put_role_mapping_response", true, args -> new PutRoleMappingResponse((boolean) args[0])); static { - PARSER.declareBoolean(constructorArg(), new ParseField("created")); - // To parse the "created" field we declare "role_mapping" field object. - // Once the nested field "created" is found parser constructs the target object and - // ignores the role_mapping object. - PARSER.declareObject((a,b) -> {}, (parser, context) -> null, new ParseField("role_mapping")); + ConstructingObjectParser roleMappingParser = new ConstructingObjectParser<>( + "put_role_mapping_response.role_mapping", true, args -> (Boolean) args[0]); + roleMappingParser.declareBoolean(constructorArg(), new ParseField("created")); + PARSER.declareObject(constructorArg(), roleMappingParser::parse, new ParseField("role_mapping")); } public static PutRoleMappingResponse fromXContent(XContentParser parser) throws IOException { diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java index d0cc929b56d..219c3c5bbba 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/ObjectParser.java @@ -324,9 +324,31 @@ public final class ObjectParser extends AbstractObjectParser, Void> parser = new ObjectParser<>("noopy", AtomicReference::new); + parser.declareString(AtomicReference::set, new ParseField("body")); + parser.declareObject((a,b) -> {}, (p, c) -> null, new ParseField("noop")); + + assertEquals("i", parser.parse(createParser(JsonXContent.jsonXContent, "{\"body\": \"i\"}"), null).get()); + Exception garbageException = expectThrows(IllegalStateException.class, () -> parser.parse( + createParser(JsonXContent.jsonXContent, "{\"noop\": {\"garbage\": \"shouldn't\"}}"), + null)); + assertEquals("parser for [noop] did not end on END_OBJECT", garbageException.getMessage()); + Exception sneakyException = expectThrows(IllegalStateException.class, () -> parser.parse( + createParser(JsonXContent.jsonXContent, "{\"noop\": {\"body\": \"shouldn't\"}}"), + null)); + assertEquals("parser for [noop] did not end on END_OBJECT", sneakyException.getMessage()); + } + + public void testNoopDeclareField() throws IOException { + ObjectParser, Void> parser = new ObjectParser<>("noopy", AtomicReference::new); + parser.declareString(AtomicReference::set, new ParseField("body")); + parser.declareField((a,b) -> {}, (p, c) -> null, new ParseField("noop"), ValueType.STRING_ARRAY); + + assertEquals("i", parser.parse(createParser(JsonXContent.jsonXContent, "{\"body\": \"i\"}"), null).get()); + Exception e = expectThrows(IllegalStateException.class, () -> parser.parse( + createParser(JsonXContent.jsonXContent, "{\"noop\": [\"ignored\"]}"), + null)); + assertEquals("parser for [noop] did not end on END_ARRAY", e.getMessage()); + } + + public void testNoopDeclareObjectArray() throws IOException { + ObjectParser, Void> parser = new ObjectParser<>("noopy", AtomicReference::new); + parser.declareString(AtomicReference::set, new ParseField("body")); + parser.declareObjectArray((a,b) -> {}, (p, c) -> null, new ParseField("noop")); + + XContentParseException garbageError = expectThrows(XContentParseException.class, () -> parser.parse( + createParser(JsonXContent.jsonXContent, "{\"noop\": [{\"garbage\": \"shouldn't\"}}]"), + null)); + assertEquals("expected value but got [FIELD_NAME]", garbageError.getCause().getMessage()); + XContentParseException sneakyError = expectThrows(XContentParseException.class, () -> parser.parse( + createParser(JsonXContent.jsonXContent, "{\"noop\": [{\"body\": \"shouldn't\"}}]"), + null)); + assertEquals("expected value but got [FIELD_NAME]", sneakyError.getCause().getMessage()); + } + static class NamedObjectHolder { public static final ObjectParser PARSER = new ObjectParser<>("named_object_holder", NamedObjectHolder::new);