|
@@ -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<Supplier<AllocationCommand>> 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<String, String> 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);
|
|
|
+ }
|
|
|
+}
|