diff --git a/build.gradle b/build.gradle index a75d093664f..4253e13f2c5 100644 --- a/build.gradle +++ b/build.gradle @@ -173,8 +173,8 @@ task verifyVersions { * the enabled state of every bwc task. It should be set back to true * after the backport of the backcompat code is complete. */ -final boolean bwc_tests_enabled = true -final String bwc_tests_disabled_issue = "" /* place a PR link here when committing bwc changes */ +final boolean bwc_tests_enabled = false +final String bwc_tests_disabled_issue = "https://github.com/elastic/elasticsearch/issues/32006" // BWC handled at a later time if (bwc_tests_enabled == false) { if (bwc_tests_disabled_issue.isEmpty()) { throw new GradleException("bwc_tests_disabled_issue must be set when bwc_tests_enabled == false") diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java index b7ef075a59a..4defd09485e 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java @@ -76,8 +76,11 @@ public class TransportClusterStateAction extends TransportMasterNodeReadAction public static final long UNKNOWN_VERSION = -1; + private final long term; + private final long version; private final String stateUUID; @@ -172,16 +182,23 @@ public class ClusterState implements ToXContentFragment, Diffable private final boolean wasReadFromDiff; + private final VotingConfiguration lastCommittedConfiguration; + + private final VotingConfiguration lastAcceptedConfiguration; + // built on demand private volatile RoutingNodes routingNodes; - public ClusterState(long version, String stateUUID, ClusterState state) { - this(state.clusterName, version, stateUUID, state.metaData(), state.routingTable(), state.nodes(), state.blocks(), state.customs(), - false); + public ClusterState(long term, long version, String stateUUID, ClusterState state) { + this(state.clusterName, term, version, stateUUID, state.metaData(), state.routingTable(), state.nodes(), state.blocks(), + state.customs(), state.getLastCommittedConfiguration(), state.getLastAcceptedConfiguration(), false); } - public ClusterState(ClusterName clusterName, long version, String stateUUID, MetaData metaData, RoutingTable routingTable, - DiscoveryNodes nodes, ClusterBlocks blocks, ImmutableOpenMap customs, boolean wasReadFromDiff) { + public ClusterState(ClusterName clusterName, long term, long version, String stateUUID, MetaData metaData, RoutingTable routingTable, + DiscoveryNodes nodes, ClusterBlocks blocks, ImmutableOpenMap customs, + VotingConfiguration lastCommittedConfiguration, VotingConfiguration lastAcceptedConfiguration, + boolean wasReadFromDiff) { + this.term = term; this.version = version; this.stateUUID = stateUUID; this.clusterName = clusterName; @@ -190,9 +207,15 @@ public class ClusterState implements ToXContentFragment, Diffable this.nodes = nodes; this.blocks = blocks; this.customs = customs; + this.lastCommittedConfiguration = lastCommittedConfiguration; + this.lastAcceptedConfiguration = lastAcceptedConfiguration; this.wasReadFromDiff = wasReadFromDiff; } + public long term() { + return term; + } + public long version() { return this.version; } @@ -257,6 +280,14 @@ public class ClusterState implements ToXContentFragment, Diffable return this.clusterName; } + public VotingConfiguration getLastAcceptedConfiguration() { + return lastAcceptedConfiguration; + } + + public VotingConfiguration getLastCommittedConfiguration() { + return lastCommittedConfiguration; + } + // Used for testing and logging to determine how this cluster state was send over the wire public boolean wasReadFromDiff() { return wasReadFromDiff; @@ -277,8 +308,11 @@ public class ClusterState implements ToXContentFragment, Diffable public String toString() { StringBuilder sb = new StringBuilder(); sb.append("cluster uuid: ").append(metaData.clusterUUID()).append("\n"); + sb.append("term: ").append(term).append("\n"); sb.append("version: ").append(version).append("\n"); sb.append("state uuid: ").append(stateUUID).append("\n"); + sb.append("last committed config: ").append(getLastCommittedConfiguration()).append("\n"); + sb.append("last accepted config: ").append(getLastAcceptedConfiguration()).append("\n"); sb.append("from_diff: ").append(wasReadFromDiff).append("\n"); sb.append("meta data version: ").append(metaData.version()).append("\n"); final String TAB = " "; @@ -386,8 +420,11 @@ public class ClusterState implements ToXContentFragment, Diffable builder.field("cluster_uuid", metaData().clusterUUID()); if (metrics.contains(Metric.VERSION)) { + builder.field("term", term); builder.field("version", version); builder.field("state_uuid", stateUUID); + builder.field("last_committed_config", lastCommittedConfiguration); + builder.field("last_accepted_config", lastAcceptedConfiguration); } if (metrics.contains(Metric.MASTER_NODE)) { @@ -587,8 +624,11 @@ public class ClusterState implements ToXContentFragment, Diffable public static class Builder { private final ClusterName clusterName; + private long term = 0; private long version = 0; private String uuid = UNKNOWN_UUID; + private VotingConfiguration lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG; + private VotingConfiguration lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG; private MetaData metaData = MetaData.EMPTY_META_DATA; private RoutingTable routingTable = RoutingTable.EMPTY_ROUTING_TABLE; private DiscoveryNodes nodes = DiscoveryNodes.EMPTY_NODES; @@ -599,8 +639,11 @@ public class ClusterState implements ToXContentFragment, Diffable public Builder(ClusterState state) { this.clusterName = state.clusterName; + this.term = state.term(); this.version = state.version(); this.uuid = state.stateUUID(); + this.lastCommittedConfiguration = state.getLastCommittedConfiguration(); + this.lastAcceptedConfiguration = state.getLastAcceptedConfiguration(); this.nodes = state.nodes(); this.routingTable = state.routingTable(); this.metaData = state.metaData(); @@ -650,6 +693,11 @@ public class ClusterState implements ToXContentFragment, Diffable return this; } + public Builder term(long term) { + this.term = term; + return this; + } + public Builder version(long version) { this.version = version; return this; @@ -666,6 +714,16 @@ public class ClusterState implements ToXContentFragment, Diffable return this; } + public Builder lastCommittedConfiguration(VotingConfiguration config) { + this.lastCommittedConfiguration = config; + return this; + } + + public Builder lastAcceptedConfiguration(VotingConfiguration config) { + this.lastAcceptedConfiguration = config; + return this; + } + public Builder putCustom(String type, Custom custom) { customs.put(type, custom); return this; @@ -690,7 +748,8 @@ public class ClusterState implements ToXContentFragment, Diffable if (UNKNOWN_UUID.equals(uuid)) { uuid = UUIDs.randomBase64UUID(); } - return new ClusterState(clusterName, version, uuid, metaData, routingTable, nodes, blocks, customs.build(), fromDiff); + return new ClusterState(clusterName, term, version, uuid, metaData, routingTable, nodes, blocks, customs.build(), + lastCommittedConfiguration, lastAcceptedConfiguration, fromDiff); } public static byte[] toBytes(ClusterState state) throws IOException { @@ -722,8 +781,15 @@ public class ClusterState implements ToXContentFragment, Diffable public static ClusterState readFrom(StreamInput in, DiscoveryNode localNode) throws IOException { ClusterName clusterName = new ClusterName(in); Builder builder = new Builder(clusterName); + if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + builder.term = in.readLong(); + } builder.version = in.readLong(); builder.uuid = in.readString(); + if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + builder.lastCommittedConfiguration(new VotingConfiguration(in)); + builder.lastAcceptedConfiguration(new VotingConfiguration(in)); + } builder.metaData = MetaData.readFrom(in); builder.routingTable = RoutingTable.readFrom(in); builder.nodes = DiscoveryNodes.readFrom(in, localNode); @@ -739,8 +805,15 @@ public class ClusterState implements ToXContentFragment, Diffable @Override public void writeTo(StreamOutput out) throws IOException { clusterName.writeTo(out); + if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + out.writeLong(term); + } out.writeLong(version); out.writeString(stateUUID); + if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + lastCommittedConfiguration.writeTo(out); + lastAcceptedConfiguration.writeTo(out); + } metaData.writeTo(out); routingTable.writeTo(out); nodes.writeTo(out); @@ -762,6 +835,8 @@ public class ClusterState implements ToXContentFragment, Diffable private static class ClusterStateDiff implements Diff { + private final long toTerm; + private final long toVersion; private final String fromUuid; @@ -770,6 +845,10 @@ public class ClusterState implements ToXContentFragment, Diffable private final ClusterName clusterName; + private final VotingConfiguration lastCommittedConfiguration; + + private final VotingConfiguration lastAcceptedConfiguration; + private final Diff routingTable; private final Diff nodes; @@ -783,8 +862,11 @@ public class ClusterState implements ToXContentFragment, Diffable ClusterStateDiff(ClusterState before, ClusterState after) { fromUuid = before.stateUUID; toUuid = after.stateUUID; + toTerm = after.term; toVersion = after.version; clusterName = after.clusterName; + lastCommittedConfiguration = after.lastCommittedConfiguration; + lastAcceptedConfiguration = after.lastAcceptedConfiguration; routingTable = after.routingTable.diff(before.routingTable); nodes = after.nodes.diff(before.nodes); metaData = after.metaData.diff(before.metaData); @@ -796,7 +878,19 @@ public class ClusterState implements ToXContentFragment, Diffable clusterName = new ClusterName(in); fromUuid = in.readString(); toUuid = in.readString(); + if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + toTerm = in.readLong(); + } else { + toTerm = 0L; + } toVersion = in.readLong(); + if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + lastCommittedConfiguration = new VotingConfiguration(in); + lastAcceptedConfiguration = new VotingConfiguration(in); + } else { + lastCommittedConfiguration = VotingConfiguration.EMPTY_CONFIG; + lastAcceptedConfiguration = VotingConfiguration.EMPTY_CONFIG; + } routingTable = RoutingTable.readDiffFrom(in); nodes = DiscoveryNodes.readDiffFrom(in, localNode); metaData = MetaData.readDiffFrom(in); @@ -809,7 +903,14 @@ public class ClusterState implements ToXContentFragment, Diffable clusterName.writeTo(out); out.writeString(fromUuid); out.writeString(toUuid); + if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + out.writeLong(toTerm); + } out.writeLong(toVersion); + if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + lastCommittedConfiguration.writeTo(out); + lastAcceptedConfiguration.writeTo(out); + } routingTable.writeTo(out); nodes.writeTo(out); metaData.writeTo(out); @@ -828,7 +929,10 @@ public class ClusterState implements ToXContentFragment, Diffable throw new IncompatibleClusterStateVersionException(state.version, state.stateUUID, toVersion, fromUuid); } builder.stateUUID(toUuid); + builder.term(toTerm); builder.version(toVersion); + builder.lastCommittedConfiguration(lastCommittedConfiguration); + builder.lastAcceptedConfiguration(lastAcceptedConfiguration); builder.routingTable(routingTable.apply(state.routingTable)); builder.nodes(nodes.apply(state.nodes)); builder.metaData(metaData.apply(state.metaData)); @@ -840,4 +944,67 @@ public class ClusterState implements ToXContentFragment, Diffable } + /** + * A collection of persistent node ids, denoting the voting configuration for cluster state changes. + */ + public static class VotingConfiguration implements Writeable, ToXContentFragment { + + public static final VotingConfiguration EMPTY_CONFIG = new VotingConfiguration(Collections.emptySet()); + + private final Set nodeIds; + + public VotingConfiguration(Set nodeIds) { + this.nodeIds = Collections.unmodifiableSet(new HashSet<>(nodeIds)); + } + + public VotingConfiguration(StreamInput in) throws IOException { + nodeIds = Collections.unmodifiableSet(Sets.newHashSet(in.readStringArray())); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeStringArray(nodeIds.toArray(new String[nodeIds.size()])); + } + + public boolean hasQuorum(Collection votes) { + final HashSet intersection = new HashSet<>(nodeIds); + intersection.retainAll(votes); + return intersection.size() * 2 > nodeIds.size(); + } + + public Set getNodeIds() { + return nodeIds; + } + + @Override + public String toString() { + return "VotingConfiguration{" + String.join(",", nodeIds) + "}"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + VotingConfiguration that = (VotingConfiguration) o; + return Objects.equals(nodeIds, that.nodeIds); + } + + @Override + public int hashCode() { + return Objects.hash(nodeIds); + } + + public boolean isEmpty() { + return nodeIds.isEmpty(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startArray(); + for (String nodeId : nodeIds) { + builder.value(nodeId); + } + return builder.endArray(); + } + } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java index 7d671096514..20a9035df9a 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java @@ -70,8 +70,11 @@ public class ClusterRerouteResponseTests extends ESTestCase { " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + + " \"term\" : 0,\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + + " \"last_committed_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ],\n" + " \"master_node\" : \"node0\",\n" + " \"blocks\" : { },\n" + " \"nodes\" : {\n" + @@ -138,8 +141,11 @@ public class ClusterRerouteResponseTests extends ESTestCase { " \"acknowledged\" : true,\n" + " \"state\" : {\n" + " \"cluster_uuid\" : \"_na_\",\n" + + " \"term\" : 0,\n" + " \"version\" : 0,\n" + " \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" + + " \"last_committed_config\" : [ ],\n" + + " \"last_accepted_config\" : [ ],\n" + " \"master_node\" : \"node0\"\n" + " },\n" + " \"explanations\" : [\n" + diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java index a5d865a2741..da1924140b0 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateDiffIT.java @@ -97,7 +97,7 @@ public class ClusterStateDiffIT extends ESIntegTestCase { if (i > 0) { clusterState = builder.build(); } - switch (randomInt(4)) { + switch (randomInt(5)) { case 0: builder = randomNodes(clusterState); break; @@ -113,11 +113,14 @@ public class ClusterStateDiffIT extends ESIntegTestCase { case 4: builder = randomMetaDataChanges(clusterState); break; + case 5: + builder = randomVotingConfiguration(clusterState); + break; default: throw new IllegalArgumentException("Shouldn't be here"); } } - clusterState = builder.incrementVersion().build(); + clusterState = builder.incrementVersion().term(randomLong()).build(); if (randomIntBetween(0, 10) < 1) { // Update cluster state via full serialization from time to time @@ -141,7 +144,10 @@ public class ClusterStateDiffIT extends ESIntegTestCase { try { // Check non-diffable elements assertThat(clusterStateFromDiffs.version(), equalTo(clusterState.version())); + assertThat(clusterStateFromDiffs.term(), equalTo(clusterState.term())); assertThat(clusterStateFromDiffs.stateUUID(), equalTo(clusterState.stateUUID())); + assertThat(clusterStateFromDiffs.getLastAcceptedConfiguration(), equalTo(clusterState.getLastAcceptedConfiguration())); + assertThat(clusterStateFromDiffs.getLastCommittedConfiguration(), equalTo(clusterState.getLastCommittedConfiguration())); // Check nodes assertThat(clusterStateFromDiffs.nodes().getNodes(), equalTo(clusterState.nodes().getNodes())); @@ -190,6 +196,20 @@ public class ClusterStateDiffIT extends ESIntegTestCase { } + private ClusterState.Builder randomVotingConfiguration(ClusterState clusterState) { + ClusterState.Builder builder = ClusterState.builder(clusterState); + if (randomBoolean()) { + builder.lastCommittedConfiguration( + new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); + } + if (randomBoolean()) { + builder.lastAcceptedConfiguration( + new ClusterState.VotingConfiguration(Sets.newHashSet(generateRandomStringArray(10, 10, false)))); + } + + return builder; + } + /** * Randomly updates nodes in the cluster state */ diff --git a/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java b/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java index 21c661230eb..7d900406e08 100644 --- a/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/ClusterStateTests.java @@ -19,10 +19,18 @@ package org.elasticsearch.cluster; import org.elasticsearch.Version; +import org.elasticsearch.cluster.ClusterState.VotingConfiguration; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.EqualsHashCodeTestUtils; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; @@ -55,6 +63,70 @@ public class ClusterStateTests extends ESTestCase { // state from the same master compare by version assertThat(withMaster1a.supersedes(withMaster1b), equalTo(withMaster1a.version() > withMaster1b.version())); + } + public void testVotingConfiguration() { + VotingConfiguration config0 = new VotingConfiguration(Sets.newHashSet()); + assertThat(config0, equalTo(VotingConfiguration.EMPTY_CONFIG)); + assertThat(config0.getNodeIds(), equalTo(Sets.newHashSet())); + assertThat(config0.isEmpty(), equalTo(true)); + assertThat(config0.hasQuorum(Sets.newHashSet()), equalTo(false)); + assertThat(config0.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); + + VotingConfiguration config1 = new VotingConfiguration(Sets.newHashSet("id1")); + assertThat(config1.getNodeIds(), equalTo(Sets.newHashSet("id1"))); + assertThat(config1.isEmpty(), equalTo(false)); + assertThat(config1.hasQuorum(Sets.newHashSet("id1")), equalTo(true)); + assertThat(config1.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); + assertThat(config1.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); + assertThat(config1.hasQuorum(Sets.newHashSet()), equalTo(false)); + + VotingConfiguration config2 = new VotingConfiguration(Sets.newHashSet("id1", "id2")); + assertThat(config2.getNodeIds(), equalTo(Sets.newHashSet("id1", "id2"))); + assertThat(config2.isEmpty(), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id2", "id3")), equalTo(true)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id3")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet("id1", "id3")), equalTo(false)); + assertThat(config2.hasQuorum(Sets.newHashSet()), equalTo(false)); + + VotingConfiguration config3 = new VotingConfiguration(Sets.newHashSet("id1", "id2", "id3")); + assertThat(config3.getNodeIds(), equalTo(Sets.newHashSet("id1", "id2", "id3"))); + assertThat(config3.isEmpty(), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id2", "id3")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id3")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2", "id3")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id2", "id4")), equalTo(true)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id2")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id3")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id4")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet("id1", "id4", "id5")), equalTo(false)); + assertThat(config3.hasQuorum(Sets.newHashSet()), equalTo(false)); + } + + public void testVotingConfigurationSerializationEqualsHashCode() { + VotingConfiguration initialConfig = new VotingConfiguration( + Sets.newHashSet(generateRandomStringArray(randomInt(10), 20, false))); + EqualsHashCodeTestUtils.checkEqualsAndHashCode(initialConfig, + orig -> ESTestCase.copyWriteable(orig, new NamedWriteableRegistry(Collections.emptyList()), VotingConfiguration::new), + cfg -> { + Set newNodeIds = new HashSet<>(cfg.getNodeIds()); + if (cfg.isEmpty() == false && randomBoolean()) { + // remove random element + newNodeIds.remove(randomFrom(cfg.getNodeIds())); + } else if (cfg.isEmpty() == false && randomBoolean()) { + // change random element + newNodeIds.remove(randomFrom(cfg.getNodeIds())); + newNodeIds.add(randomAlphaOfLength(20)); + } else { + // add random element + newNodeIds.add(randomAlphaOfLength(20)); + } + return new VotingConfiguration(newNodeIds); + }); } } diff --git a/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java b/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java index ac1719269e7..0503a4f819d 100644 --- a/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java +++ b/server/src/test/java/org/elasticsearch/discovery/zen/PublishClusterStateActionTests.java @@ -487,7 +487,8 @@ public class PublishClusterStateActionTests extends ESTestCase { clusterState = ClusterState.builder(clusterState).blocks(ClusterBlocks.builder() .addGlobalBlock(MetaData.CLUSTER_READ_ONLY_BLOCK)).incrementVersion().build(); - ClusterState unserializableClusterState = new ClusterState(clusterState.version(), clusterState.stateUUID(), clusterState) { + ClusterState unserializableClusterState = new ClusterState(clusterState.term(), clusterState.version(), clusterState.stateUUID(), + clusterState) { @Override public Diff diff(ClusterState previousState) { return new Diff() { diff --git a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java index 098f4190b0e..076fe596e52 100644 --- a/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java +++ b/x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java @@ -504,8 +504,11 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase