-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds wait_for_no_initializing_shards to cluster health API #27489
Changes from 5 commits
f5b32d4
79f6d3b
9f7e59c
4405767
04e61fb
dd2294f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* 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.health; | ||
|
||
import org.elasticsearch.cluster.health.ClusterHealthStatus; | ||
import org.elasticsearch.common.Priority; | ||
import org.elasticsearch.common.io.stream.BytesStreamOutput; | ||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
import static org.hamcrest.core.IsEqual.equalTo; | ||
|
||
public class ClusterHealthRequestTests extends ESTestCase { | ||
public void testSerialize() throws Exception { | ||
final ClusterHealthRequest originalRequest = randomRequest(); | ||
final ClusterHealthRequest cloneRequest; | ||
try (BytesStreamOutput out = new BytesStreamOutput()) { | ||
originalRequest.writeTo(out); | ||
try (StreamInput in = out.bytes().streamInput()) { | ||
cloneRequest = new ClusterHealthRequest(in); | ||
} | ||
} | ||
assertThat(cloneRequest.waitForStatus(), equalTo(originalRequest.waitForStatus())); | ||
assertThat(cloneRequest.waitForNodes(), equalTo(originalRequest.waitForNodes())); | ||
assertThat(cloneRequest.waitForNoInitializingShards(), equalTo(originalRequest.waitForNoInitializingShards())); | ||
assertThat(cloneRequest.waitForNoRelocatingShards(), equalTo(originalRequest.waitForNoRelocatingShards())); | ||
assertThat(cloneRequest.waitForActiveShards(), equalTo(originalRequest.waitForActiveShards())); | ||
assertThat(cloneRequest.waitForEvents(), equalTo(originalRequest.waitForEvents())); | ||
} | ||
|
||
ClusterHealthRequest randomRequest() { | ||
ClusterHealthRequest request = new ClusterHealthRequest(); | ||
request.waitForStatus(randomFrom(ClusterHealthStatus.values())); | ||
request.waitForNodes(randomFrom("", "<", "<=", ">", ">=") + between(0, 1000)); | ||
request.waitForNoInitializingShards(randomBoolean()); | ||
request.waitForNoRelocatingShards(randomBoolean()); | ||
request.waitForActiveShards(randomIntBetween(0, 10)); | ||
request.waitForEvents(randomFrom(Priority.values())); | ||
return request; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* 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.health; | ||
|
||
import org.elasticsearch.Version; | ||
import org.elasticsearch.cluster.ClusterName; | ||
import org.elasticsearch.cluster.ClusterState; | ||
import org.elasticsearch.cluster.metadata.IndexMetaData; | ||
import org.elasticsearch.cluster.metadata.MetaData; | ||
import org.elasticsearch.cluster.routing.IndexRoutingTable; | ||
import org.elasticsearch.cluster.routing.RoutingTable; | ||
import org.elasticsearch.cluster.routing.ShardRoutingState; | ||
import org.elasticsearch.cluster.routing.TestShardRouting; | ||
import org.elasticsearch.common.Randomness; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.index.Index; | ||
import org.elasticsearch.index.shard.ShardId; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.stream.IntStream; | ||
|
||
import static org.hamcrest.core.IsEqual.equalTo; | ||
|
||
public class TransportClusterHealthActionTests extends ESTestCase { | ||
|
||
public void testWaitForInitializingShards() throws Exception { | ||
final String[] indices = {"test"}; | ||
final ClusterHealthRequest request = new ClusterHealthRequest(); | ||
request.waitForNoInitializingShards(true); | ||
ClusterState clusterState = randomClusterStateWithInitializingShards("test", 0); | ||
ClusterHealthResponse response = new ClusterHealthResponse("", indices, clusterState); | ||
assertThat(TransportClusterHealthAction.prepareResponse(request, response, clusterState, null), equalTo(1)); | ||
|
||
request.waitForNoInitializingShards(true); | ||
clusterState = randomClusterStateWithInitializingShards("test", between(1, 10)); | ||
response = new ClusterHealthResponse("", indices, clusterState); | ||
assertThat(TransportClusterHealthAction.prepareResponse(request, response, clusterState, null), equalTo(0)); | ||
|
||
request.waitForNoInitializingShards(false); | ||
clusterState = randomClusterStateWithInitializingShards("test", randomInt(20)); | ||
response = new ClusterHealthResponse("", indices, clusterState); | ||
assertThat(TransportClusterHealthAction.prepareResponse(request, response, clusterState, null), equalTo(0)); | ||
} | ||
|
||
ClusterState randomClusterStateWithInitializingShards(String index, final int initializingShards) { | ||
final IndexMetaData indexMetaData = IndexMetaData | ||
.builder(index) | ||
.settings(settings(Version.CURRENT)) | ||
.numberOfShards(between(1, 10)) | ||
.numberOfReplicas(randomInt(20)) | ||
.build(); | ||
|
||
final List<ShardRoutingState> shardRoutingStates = new ArrayList<>(); | ||
IntStream.range(0, between(1, 30)).forEach(i -> shardRoutingStates.add(randomFrom( | ||
ShardRoutingState.STARTED, ShardRoutingState.UNASSIGNED, ShardRoutingState.RELOCATING))); | ||
IntStream.range(0, initializingShards).forEach(i -> shardRoutingStates.add(ShardRoutingState.INITIALIZING)); | ||
Randomness.shuffle(shardRoutingStates); | ||
|
||
final ShardId shardId = new ShardId(new Index("index", "uuid"), 0); | ||
final IndexRoutingTable.Builder routingTable = new IndexRoutingTable.Builder(indexMetaData.getIndex()); | ||
|
||
// Primary | ||
{ | ||
ShardRoutingState state = shardRoutingStates.remove(0); | ||
String node = state == ShardRoutingState.UNASSIGNED ? null : "node"; | ||
routingTable.addShard( | ||
TestShardRouting.newShardRouting(shardId, node, "relocating", true, state) | ||
); | ||
} | ||
|
||
// Replicas | ||
for (int i = 0; i < shardRoutingStates.size(); i++) { | ||
ShardRoutingState state = shardRoutingStates.get(i); | ||
String node = state == ShardRoutingState.UNASSIGNED ? null : "node" + i; | ||
routingTable.addShard(TestShardRouting.newShardRouting(shardId, node, "relocating"+i, randomBoolean(), state)); | ||
} | ||
|
||
return ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.getDefault(Settings.EMPTY)) | ||
.metaData(MetaData.builder().put(indexMetaData, true)) | ||
.routingTable(RoutingTable.builder().add(routingTable.build()).build()) | ||
.build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -92,6 +92,37 @@ | |
- match: { unassigned_shards: 0 } | ||
- gte: { number_of_pending_tasks: 0 } | ||
|
||
--- | ||
"cluster health basic test, one index with wait for no initializing shards": | ||
- skip: | ||
version: " - 6.99.99" | ||
reason: "wait_for_no_initializing_shard is introduced in 7.0.0" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wait_for_no_initializing_shards |
||
|
||
- do: | ||
indices.create: | ||
index: test_index | ||
wait_for_active_shards: 0 | ||
body: | ||
settings: | ||
index: | ||
number_of_shards: 50 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default of 5 is good enough (slow CI machines ftw) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I had to increase it to see the difference on my machine. |
||
number_of_replicas: 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. creating an index automatically waits for primary to be allocated (wait_for_active_shards is 1 by default). This means that the health check later is fully redundant, it will always succeed. This test does not really test anything here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how about changing it so that the index is created with wait_for_active_shards : 0? Then this health check will actually wait for the primaries to be allocated and the output should guarantee that number of initializing shards is 0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
- do: | ||
cluster.health: | ||
wait_for_no_initializing_shards: true | ||
|
||
- is_true: cluster_name | ||
- is_false: timed_out | ||
- gte: { number_of_nodes: 1 } | ||
- gte: { number_of_data_nodes: 1 } | ||
- match: { active_primary_shards: 50} | ||
- gt: { active_shards: 0 } | ||
- gte: { relocating_shards: 0 } | ||
- match: { initializing_shards: 0 } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's good enough to just test this match. The other ones are covered by other tests in this same file. |
||
- match: { unassigned_shards: 0 } | ||
- gte: { number_of_pending_tasks: 0 } | ||
|
||
--- | ||
"cluster health levels": | ||
- do: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh missed that, sorry.