diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml
index 90b8aa8423f..63133dd851b 100644
--- a/buildSrc/src/main/resources/checkstyle_suppressions.xml
+++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml
@@ -37,8 +37,6 @@
-
-
diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java
index dcc45ab21b9..4ec729bbc53 100644
--- a/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java
+++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequest.java
@@ -19,20 +19,15 @@
package org.elasticsearch.action.admin.cluster.reroute;
-import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
-import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands;
-import org.elasticsearch.common.ParseFieldMatcher;
-import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.xcontent.XContentHelper;
-import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
+import java.util.Objects;
/**
* Request to submit cluster reroute allocation commands
@@ -109,8 +104,8 @@ public class ClusterRerouteRequest extends AcknowledgedRequest {
-
+public class ClusterRerouteRequestBuilder
+ extends AcknowledgedRequestBuilder {
public ClusterRerouteRequestBuilder(ElasticsearchClient client, ClusterRerouteAction action) {
super(client, action, new ClusterRerouteRequest());
}
@@ -68,12 +67,4 @@ public class ClusterRerouteRequestBuilder extends AcknowledgedRequestBuilder {
diff --git a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/AllocationCommands.java b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/AllocationCommands.java
index ca0eab6e33b..10ba3f55944 100644
--- a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/AllocationCommands.java
+++ b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/AllocationCommands.java
@@ -20,12 +20,12 @@
package org.elasticsearch.cluster.routing.allocation.command;
import org.elasticsearch.ElasticsearchParseException;
+import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
import org.elasticsearch.cluster.routing.allocation.RoutingExplanations;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@@ -33,12 +33,13 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* A simple {@link AllocationCommand} composite managing several
* {@link AllocationCommand} implementations
*/
-public class AllocationCommands {
+public class AllocationCommands extends ToXContentToBytes {
private final List commands = new ArrayList<>();
/**
@@ -171,21 +172,31 @@ public class AllocationCommands {
return commands;
}
- /**
- * Writes {@link AllocationCommands} to a {@link XContentBuilder}
- *
- * @param commands {@link AllocationCommands} to write
- * @param builder {@link XContentBuilder} to use
- * @param params Parameters to use for building
- * @throws IOException if something bad happens while building the content
- */
- public static void toXContent(AllocationCommands commands, XContentBuilder builder, ToXContent.Params params) throws IOException {
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startArray("commands");
- for (AllocationCommand command : commands.commands) {
+ for (AllocationCommand command : commands) {
builder.startObject();
builder.field(command.name(), command);
builder.endObject();
}
builder.endArray();
+ return builder;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ AllocationCommands other = (AllocationCommands) obj;
+ // Override equals and hashCode for testing
+ return Objects.equals(commands, other.commands);
+ }
+
+ @Override
+ public int hashCode() {
+ // Override equals and hashCode for testing
+ return Objects.hashCode(commands);
}
}
diff --git a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/BasePrimaryAllocationCommand.java b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/BasePrimaryAllocationCommand.java
index 0013061e8ea..2eb3af9d4f9 100644
--- a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/BasePrimaryAllocationCommand.java
+++ b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/BasePrimaryAllocationCommand.java
@@ -83,4 +83,18 @@ public abstract class BasePrimaryAllocationCommand extends AbstractAllocateAlloc
protected void extraXContent(XContentBuilder builder) throws IOException {
builder.field(ACCEPT_DATA_LOSS_FIELD, acceptDataLoss);
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (false == super.equals(obj)) {
+ return false;
+ }
+ BasePrimaryAllocationCommand other = (BasePrimaryAllocationCommand) obj;
+ return acceptDataLoss == other.acceptDataLoss;
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * super.hashCode() + Boolean.hashCode(acceptDataLoss);
+ }
}
diff --git a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/CancelAllocationCommand.java b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/CancelAllocationCommand.java
index 60b0842b273..9adb3e30708 100644
--- a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/CancelAllocationCommand.java
+++ b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/CancelAllocationCommand.java
@@ -35,6 +35,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
+import java.util.Objects;
import static org.elasticsearch.cluster.routing.ShardRoutingState.RELOCATING;
@@ -240,4 +241,23 @@ public class CancelAllocationCommand implements AllocationCommand {
}
return new CancelAllocationCommand(index, shardId, nodeId, allowPrimary);
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ CancelAllocationCommand other = (CancelAllocationCommand) obj;
+ // Override equals and hashCode for testing
+ return Objects.equals(index, other.index) &&
+ Objects.equals(shardId, other.shardId) &&
+ Objects.equals(node, other.node) &&
+ Objects.equals(allowPrimary, other.allowPrimary);
+ }
+
+ @Override
+ public int hashCode() {
+ // Override equals and hashCode for testing
+ return Objects.hash(index, shardId, node, allowPrimary);
+ }
}
diff --git a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/MoveAllocationCommand.java b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/MoveAllocationCommand.java
index a2e1a54e515..69bd8f0eeca 100644
--- a/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/MoveAllocationCommand.java
+++ b/core/src/main/java/org/elasticsearch/cluster/routing/allocation/command/MoveAllocationCommand.java
@@ -34,6 +34,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
+import java.util.Objects;
/**
* A command that moves a shard from a specific node to another node.
@@ -195,4 +196,23 @@ public class MoveAllocationCommand implements AllocationCommand {
}
return new MoveAllocationCommand(index, shardId, fromNode, toNode);
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ MoveAllocationCommand other = (MoveAllocationCommand) obj;
+ // Override equals and hashCode for testing
+ return Objects.equals(index, other.index) &&
+ Objects.equals(shardId, other.shardId) &&
+ Objects.equals(fromNode, other.fromNode) &&
+ Objects.equals(toNode, other.toNode);
+ }
+
+ @Override
+ public int hashCode() {
+ // Override equals and hashCode for testing
+ return Objects.hash(index, shardId, fromNode, toNode);
+ }
}
diff --git a/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java b/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java
index eebd8544bf8..201e5297511 100644
--- a/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java
+++ b/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java
@@ -19,9 +19,6 @@
package org.elasticsearch.common.network;
-import java.util.Arrays;
-import java.util.List;
-
import org.elasticsearch.action.support.replication.ReplicationTask;
import org.elasticsearch.client.transport.TransportClientNodesService;
import org.elasticsearch.client.transport.support.TransportProxyClient;
@@ -68,6 +65,12 @@ import org.elasticsearch.rest.action.admin.cluster.snapshots.restore.RestRestore
import org.elasticsearch.rest.action.admin.cluster.snapshots.status.RestSnapshotsStatusAction;
import org.elasticsearch.rest.action.admin.cluster.state.RestClusterStateAction;
import org.elasticsearch.rest.action.admin.cluster.stats.RestClusterStatsAction;
+import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteSearchTemplateAction;
+import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteStoredScriptAction;
+import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetSearchTemplateAction;
+import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetStoredScriptAction;
+import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutSearchTemplateAction;
+import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutStoredScriptAction;
import org.elasticsearch.rest.action.admin.cluster.tasks.RestPendingClusterTasksAction;
import org.elasticsearch.rest.action.admin.indices.alias.RestIndicesAliasesAction;
import org.elasticsearch.rest.action.admin.indices.alias.delete.RestIndexDeleteAliasesAction;
@@ -134,17 +137,11 @@ import org.elasticsearch.rest.action.ingest.RestGetPipelineAction;
import org.elasticsearch.rest.action.ingest.RestPutPipelineAction;
import org.elasticsearch.rest.action.ingest.RestSimulatePipelineAction;
import org.elasticsearch.rest.action.main.RestMainAction;
-import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteStoredScriptAction;
-import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetStoredScriptAction;
-import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutStoredScriptAction;
import org.elasticsearch.rest.action.search.RestClearScrollAction;
import org.elasticsearch.rest.action.search.RestMultiSearchAction;
import org.elasticsearch.rest.action.search.RestSearchAction;
import org.elasticsearch.rest.action.search.RestSearchScrollAction;
import org.elasticsearch.rest.action.suggest.RestSuggestAction;
-import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestDeleteSearchTemplateAction;
-import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestGetSearchTemplateAction;
-import org.elasticsearch.rest.action.admin.cluster.storedscripts.RestPutSearchTemplateAction;
import org.elasticsearch.rest.action.termvectors.RestMultiTermVectorsAction;
import org.elasticsearch.rest.action.termvectors.RestTermVectorsAction;
import org.elasticsearch.rest.action.update.RestUpdateAction;
@@ -154,6 +151,9 @@ import org.elasticsearch.transport.TransportService;
import org.elasticsearch.transport.local.LocalTransport;
import org.elasticsearch.transport.netty.NettyTransport;
+import java.util.Arrays;
+import java.util.List;
+
/**
* A module to handle registering and binding all network related classes.
*/
@@ -397,7 +397,7 @@ public class NetworkModule extends AbstractModule {
* @param commandName the names under which the command should be parsed. The {@link ParseField#getPreferredName()} is special because
* it is the name under which the command's reader is registered.
*/
- public void registerAllocationCommand(Writeable.Reader reader, AllocationCommand.Parser parser,
+ private void registerAllocationCommand(Writeable.Reader reader, AllocationCommand.Parser parser,
ParseField commandName) {
allocationCommandRegistry.register(parser, commandName);
namedWriteableRegistry.register(AllocationCommand.class, commandName.getPreferredName(), reader);
diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/reroute/RestClusterRerouteAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/reroute/RestClusterRerouteAction.java
index b34c6726c09..a06466137a5 100644
--- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/reroute/RestClusterRerouteAction.java
+++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/reroute/RestClusterRerouteAction.java
@@ -25,12 +25,20 @@ import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
+import org.elasticsearch.cluster.routing.allocation.command.AllocationCommands;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.ParseFieldMatcher;
+import org.elasticsearch.common.ParseFieldMatcherSupplier;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsFilter;
+import org.elasticsearch.common.xcontent.ObjectParser;
+import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentHelper;
+import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
@@ -43,12 +51,17 @@ import java.util.EnumSet;
/**
*/
public class RestClusterRerouteAction extends BaseRestHandler {
+ private static final ObjectParser PARSER = new ObjectParser<>("cluster_reroute");
+ static {
+ PARSER.declareField((p, v, c) -> v.commands(AllocationCommands.fromXContent(p, c.getParseFieldMatcher(), c.registry)),
+ new ParseField("commands"), ValueType.OBJECT_ARRAY);
+ PARSER.declareBoolean(ClusterRerouteRequest::dryRun, new ParseField("dry_run"));
+ }
- private final SettingsFilter settingsFilter;
-
- private static String DEFAULT_METRICS = Strings
+ private static final String DEFAULT_METRICS = Strings
.arrayToCommaDelimitedString(EnumSet.complementOf(EnumSet.of(ClusterState.Metric.METADATA)).toArray());
+ private final SettingsFilter settingsFilter;
private final AllocationCommandRegistry registry;
@Inject
@@ -62,16 +75,7 @@ public class RestClusterRerouteAction extends BaseRestHandler {
@Override
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) throws Exception {
- final ClusterRerouteRequest clusterRerouteRequest = Requests.clusterRerouteRequest();
- clusterRerouteRequest.dryRun(request.paramAsBoolean("dry_run", clusterRerouteRequest.dryRun()));
- clusterRerouteRequest.setRetryFailed(request.paramAsBoolean("retry_failed", clusterRerouteRequest.isRetryFailed()));
- clusterRerouteRequest.explain(request.paramAsBoolean("explain", clusterRerouteRequest.explain()));
- clusterRerouteRequest.timeout(request.paramAsTime("timeout", clusterRerouteRequest.timeout()));
- clusterRerouteRequest.masterNodeTimeout(request.paramAsTime("master_timeout", clusterRerouteRequest.masterNodeTimeout()));
- if (request.hasContent()) {
- clusterRerouteRequest.source(request.content(), registry, parseFieldMatcher);
- }
-
+ ClusterRerouteRequest clusterRerouteRequest = createRequest(request, registry, parseFieldMatcher);
client.admin().cluster().reroute(clusterRerouteRequest, new AcknowledgedRestListener(channel) {
@Override
protected void addCustomFields(XContentBuilder builder, ClusterRerouteResponse response) throws IOException {
@@ -90,4 +94,35 @@ public class RestClusterRerouteAction extends BaseRestHandler {
}
});
}
+
+ public static ClusterRerouteRequest createRequest(RestRequest request, AllocationCommandRegistry registry,
+ ParseFieldMatcher parseFieldMatcher) throws IOException {
+ ClusterRerouteRequest clusterRerouteRequest = Requests.clusterRerouteRequest();
+ clusterRerouteRequest.dryRun(request.paramAsBoolean("dry_run", clusterRerouteRequest.dryRun()));
+ clusterRerouteRequest.explain(request.paramAsBoolean("explain", clusterRerouteRequest.explain()));
+ clusterRerouteRequest.timeout(request.paramAsTime("timeout", clusterRerouteRequest.timeout()));
+ clusterRerouteRequest.setRetryFailed(request.paramAsBoolean("retry_failed", clusterRerouteRequest.isRetryFailed()));
+ clusterRerouteRequest.masterNodeTimeout(request.paramAsTime("master_timeout", clusterRerouteRequest.masterNodeTimeout()));
+ if (request.hasContent()) {
+ try (XContentParser parser = XContentHelper.createParser(request.content())) {
+ PARSER.parse(parser, clusterRerouteRequest, new ParseContext(registry, parseFieldMatcher));
+ }
+ }
+ return clusterRerouteRequest;
+ }
+
+ private static class ParseContext implements ParseFieldMatcherSupplier {
+ private final AllocationCommandRegistry registry;
+ private final ParseFieldMatcher parseFieldMatcher;
+
+ private ParseContext(AllocationCommandRegistry registry, ParseFieldMatcher parseFieldMatcher) {
+ this.registry = registry;
+ this.parseFieldMatcher = parseFieldMatcher;
+ }
+
+ @Override
+ public ParseFieldMatcher getParseFieldMatcher() {
+ return parseFieldMatcher;
+ }
+ }
}
diff --git a/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java b/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java
new file mode 100644
index 00000000000..06ca3a4f869
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteRequestTests.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.
+ */
+
+package org.elasticsearch.action.admin.cluster.reroute;
+
+import org.elasticsearch.action.support.master.AcknowledgedRequest;
+import org.elasticsearch.action.support.master.MasterNodeRequest;
+import org.elasticsearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand;
+import org.elasticsearch.cluster.routing.allocation.command.AllocateReplicaAllocationCommand;
+import org.elasticsearch.cluster.routing.allocation.command.AllocateStalePrimaryAllocationCommand;
+import org.elasticsearch.cluster.routing.allocation.command.AllocationCommand;
+import org.elasticsearch.cluster.routing.allocation.command.AllocationCommandRegistry;
+import org.elasticsearch.cluster.routing.allocation.command.CancelAllocationCommand;
+import org.elasticsearch.cluster.routing.allocation.command.MoveAllocationCommand;
+import org.elasticsearch.common.ParseFieldMatcher;
+import org.elasticsearch.common.io.stream.BytesStreamOutput;
+import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
+import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.network.NetworkModule;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.rest.RestRequest;
+import org.elasticsearch.rest.action.admin.cluster.reroute.RestClusterRerouteAction;
+import org.elasticsearch.test.ESTestCase;
+import org.elasticsearch.test.rest.FakeRestRequest;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.unmodifiableList;
+import static org.elasticsearch.common.unit.TimeValue.timeValueMillis;
+
+/**
+ * Test for serialization and parsing of {@link ClusterRerouteRequest} and its commands. See the superclass for, well, everything.
+ */
+public class ClusterRerouteRequestTests extends ESTestCase {
+ private static final int ROUNDS = 30;
+ private final List> RANDOM_COMMAND_GENERATORS = unmodifiableList(Arrays.asList(
+ () -> new AllocateReplicaAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
+ randomAsciiOfLengthBetween(2, 10)),
+ () -> new AllocateEmptyPrimaryAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
+ randomAsciiOfLengthBetween(2, 10), randomBoolean()),
+ () -> new AllocateStalePrimaryAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
+ randomAsciiOfLengthBetween(2, 10), randomBoolean()),
+ () -> new CancelAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
+ randomAsciiOfLengthBetween(2, 10), randomBoolean()),
+ () -> new MoveAllocationCommand(randomAsciiOfLengthBetween(2, 10), between(0, 1000),
+ randomAsciiOfLengthBetween(2, 10), randomAsciiOfLengthBetween(2, 10))));
+ private final NamedWriteableRegistry namedWriteableRegistry;
+ private final AllocationCommandRegistry allocationCommandRegistry;
+
+ public ClusterRerouteRequestTests() {
+ namedWriteableRegistry = new NamedWriteableRegistry();
+ allocationCommandRegistry = new NetworkModule(null, null, true, namedWriteableRegistry).getAllocationCommandRegistry();
+ }
+
+ private ClusterRerouteRequest randomRequest() {
+ ClusterRerouteRequest request = new ClusterRerouteRequest();
+ int commands = between(0, 10);
+ for (int i = 0; i < commands; i++) {
+ request.add(randomFrom(RANDOM_COMMAND_GENERATORS).get());
+ }
+ request.dryRun(randomBoolean());
+ request.explain(randomBoolean());
+ request.setRetryFailed(randomBoolean());
+ return request;
+ }
+
+ public void testEqualsAndHashCode() {
+ for (int round = 0; round < ROUNDS; round++) {
+ ClusterRerouteRequest request = randomRequest();
+ assertEquals(request, request);
+ assertEquals(request.hashCode(), request.hashCode());
+
+ ClusterRerouteRequest copy = new ClusterRerouteRequest()
+ .add(request.getCommands().commands().toArray(new AllocationCommand[0]));
+ copy.dryRun(request.dryRun()).explain(request.explain()).timeout(request.timeout()).setRetryFailed(request.isRetryFailed());
+ copy.masterNodeTimeout(request.masterNodeTimeout());
+ assertEquals(request, copy);
+ assertEquals(copy, request); // Commutative
+ assertEquals(request.hashCode(), copy.hashCode());
+
+ // Changing dryRun makes requests not equal
+ copy.dryRun(!copy.dryRun());
+ assertNotEquals(request, copy);
+ assertNotEquals(request.hashCode(), copy.hashCode());
+ copy.dryRun(!copy.dryRun());
+ assertEquals(request, copy);
+ assertEquals(request.hashCode(), copy.hashCode());
+
+ // Changing explain makes requests not equal
+ copy.explain(!copy.explain());
+ assertNotEquals(request, copy);
+ assertNotEquals(request.hashCode(), copy.hashCode());
+ copy.explain(!copy.explain());
+ assertEquals(request, copy);
+ assertEquals(request.hashCode(), copy.hashCode());
+
+ // Changing timeout makes requests not equal
+ copy.timeout(timeValueMillis(request.timeout().millis() + 1));
+ assertNotEquals(request, copy);
+ assertNotEquals(request.hashCode(), copy.hashCode());
+ copy.timeout(request.timeout());
+ assertEquals(request, copy);
+ assertEquals(request.hashCode(), copy.hashCode());
+
+ // Changing masterNodeTime makes requests not equal
+ copy.masterNodeTimeout(timeValueMillis(request.masterNodeTimeout().millis() + 1));
+ assertNotEquals(request, copy);
+ assertNotEquals(request.hashCode(), copy.hashCode());
+ copy.masterNodeTimeout(request.masterNodeTimeout());
+ assertEquals(request, copy);
+ assertEquals(request.hashCode(), copy.hashCode());
+
+ // Changing commands makes requests not equal
+ copy.add(randomFrom(RANDOM_COMMAND_GENERATORS).get());
+ assertNotEquals(request, copy);
+ // Can't check hashCode because we can't be sure that changing commands changes the hashCode. It usually does but might not.
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ for (int round = 0; round < ROUNDS; round++) {
+ ClusterRerouteRequest request = randomRequest();
+ ClusterRerouteRequest copy = roundTripThroughBytes(request);
+ assertEquals(request, copy);
+ assertEquals(request.hashCode(), copy.hashCode());
+ assertNotSame(request, copy);
+ }
+ }
+
+ public void testParsing() throws IOException {
+ for (int round = 0; round < ROUNDS; round++) {
+ ClusterRerouteRequest request = randomRequest();
+ ClusterRerouteRequest copy = roundTripThroughRestRequest(request);
+ assertEquals(request, copy);
+ assertEquals(request.hashCode(), copy.hashCode());
+ assertNotSame(request, copy);
+ }
+ }
+
+ private ClusterRerouteRequest roundTripThroughBytes(ClusterRerouteRequest original) throws IOException {
+ try (BytesStreamOutput output = new BytesStreamOutput()) {
+ original.writeTo(output);
+ try (StreamInput in = new NamedWriteableAwareStreamInput(StreamInput.wrap(output.bytes()), namedWriteableRegistry)) {
+ ClusterRerouteRequest copy = new ClusterRerouteRequest();
+ copy.readFrom(in);
+ return copy;
+ }
+ }
+ }
+
+ private ClusterRerouteRequest roundTripThroughRestRequest(ClusterRerouteRequest original) throws IOException {
+ RestRequest restRequest = toRestRequest(original);
+ return RestClusterRerouteAction.createRequest(restRequest, allocationCommandRegistry, ParseFieldMatcher.STRICT);
+ }
+
+ private static RestRequest toRestRequest(ClusterRerouteRequest original) throws IOException {
+ Map params = new HashMap<>();
+ XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
+ boolean hasBody = false;
+ if (randomBoolean()) {
+ builder.prettyPrint();
+ }
+ builder.startObject();
+ if (randomBoolean()) {
+ params.put("dry_run", Boolean.toString(original.dryRun()));
+ } else {
+ hasBody = true;
+ builder.field("dry_run", original.dryRun());
+ }
+ params.put("explain", Boolean.toString(original.explain()));
+ if (false == original.timeout().equals(AcknowledgedRequest.DEFAULT_ACK_TIMEOUT) || randomBoolean()) {
+ params.put("timeout", original.timeout().toString());
+ }
+ if (original.isRetryFailed() || randomBoolean()) {
+ params.put("retry_failed", Boolean.toString(original.isRetryFailed()));
+ }
+ if (false == original.masterNodeTimeout().equals(MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT) || randomBoolean()) {
+ params.put("master_timeout", original.masterNodeTimeout().toString());
+ }
+ if (original.getCommands() != null) {
+ hasBody = true;
+ original.getCommands().toXContent(builder, ToXContent.EMPTY_PARAMS);
+ }
+ builder.endObject();
+
+ return new FakeRestRequest(emptyMap(), params, hasBody ? builder.bytes() : null);
+ }
+}
diff --git a/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java b/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java
index 927f572487c..c11bf0b9ca6 100644
--- a/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java
+++ b/core/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteTests.java
@@ -59,7 +59,7 @@ public class ClusterRerouteTests extends ESAllocationTestCase {
req.setRetryFailed(randomBoolean());
req.dryRun(randomBoolean());
req.explain(randomBoolean());
- req.commands(new AllocateEmptyPrimaryAllocationCommand("foo", 1, "bar", randomBoolean()));
+ req.add(new AllocateEmptyPrimaryAllocationCommand("foo", 1, "bar", randomBoolean()));
req.timeout(TimeValue.timeValueMillis(randomIntBetween(0, 100)));
BytesStreamOutput out = new BytesStreamOutput();
req.writeTo(out);
diff --git a/docs/reference/migration/migrate_5_0/allocation.asciidoc b/docs/reference/migration/migrate_5_0/allocation.asciidoc
index 1e095831381..d7affd8ff95 100644
--- a/docs/reference/migration/migrate_5_0/allocation.asciidoc
+++ b/docs/reference/migration/migrate_5_0/allocation.asciidoc
@@ -39,6 +39,11 @@ command corresponds to the old `allocate` command with `allow_primary` set to
false. The new `allocate_empty_primary` command corresponds to the old
`allocate` command with `allow_primary` set to true.
+==== Custom Reroute Commands
+
+Elasticsearch no longer supports plugins registering custom allocation
+commands. It was unused and hopefully unneeded.
+
==== `index.shared_filesystem.recover_on_any_node` changes
The behavior of `index.shared_filesystem.recover_on_any_node: true` has been