Skip to content

Commit a288727

Browse files
jasontedorkcm
authored andcommitted
Do not update number of replicas on no indices (#34481)
Today when submitting an update settings request to update the number of replicas with a wildcard that does not match any indices and allow no indices is set to true, the request ends up being interpreted as updating the number of replicas for all indices. That is, consider the following sequence: PUT /test-index { "settings": { "index.number_of_replicas": 0 } } PUT /non-existent-*/_settings?expand_wildcards=open&allow_no_indices=true { "settings": { "index.number_of_replicas": 1 } } GET /test-index/_settings The latter will show that the number of replicas on test-index is now one. This is surprising, and should be considered a bug. The underlying problem here is treating no indices in the underlying methods used to update the routing table and the metadata as meaning all indices. This commit takes away this assumption. Tests that relied on this behavior have been changed to no longer rely on this. A test for this situation is added in UpdateNumberOfReplicasIT.
1 parent 08a2006 commit a288727

File tree

7 files changed

+48
-17
lines changed

7 files changed

+48
-17
lines changed

server/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,10 +1034,14 @@ public Builder updateSettings(Settings settings, String... indices) {
10341034
return this;
10351035
}
10361036

1037-
public Builder updateNumberOfReplicas(int numberOfReplicas, String... indices) {
1038-
if (indices == null || indices.length == 0) {
1039-
indices = this.indices.keys().toArray(String.class);
1040-
}
1037+
/**
1038+
* Update the number of replicas for the specified indices.
1039+
*
1040+
* @param numberOfReplicas the number of replicas
1041+
* @param indices the indices to update the number of replicas for
1042+
* @return the builder
1043+
*/
1044+
public Builder updateNumberOfReplicas(final int numberOfReplicas, final String[] indices) {
10411045
for (String index : indices) {
10421046
IndexMetaData indexMetaData = this.indices.get(index);
10431047
if (indexMetaData == null) {

server/src/main/java/org/elasticsearch/cluster/routing/RoutingTable.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -457,13 +457,17 @@ public Builder updateNodes(long version, RoutingNodes routingNodes) {
457457
return this;
458458
}
459459

460-
public Builder updateNumberOfReplicas(int numberOfReplicas, String... indices) {
460+
/**
461+
* Update the number of replicas for the specified indices.
462+
*
463+
* @param numberOfReplicas the number of replicas
464+
* @param indices the indices to update the number of replicas for
465+
* @return the builder
466+
*/
467+
public Builder updateNumberOfReplicas(final int numberOfReplicas, final String[] indices) {
461468
if (indicesRouting == null) {
462469
throw new IllegalStateException("once build is called the builder cannot be reused");
463470
}
464-
if (indices == null || indices.length == 0) {
465-
indices = indicesRouting.keys().toArray(String.class);
466-
}
467471
for (String index : indices) {
468472
IndexRoutingTable indexRoutingTable = indicesRouting.get(index);
469473
if (indexRoutingTable == null) {

server/src/test/java/org/elasticsearch/cluster/routing/RoutingTableTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ public void testRoutingTableBuiltMoreThanOnce() {
275275
assertThat(e.getMessage(), containsString("cannot be reused"));
276276
}
277277
try {
278-
b.updateNumberOfReplicas(1, "foo");
278+
b.updateNumberOfReplicas(1, new String[]{"foo"});
279279
fail("expected exception");
280280
} catch (IllegalStateException e) {
281281
assertThat(e.getMessage(), containsString("cannot be reused"));

server/src/test/java/org/elasticsearch/cluster/routing/allocation/InSyncAllocationIdTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,8 @@ public void testInSyncIdsNotTrimmedWhenNotGrowing() throws Exception {
292292

293293
logger.info("decrease number of replicas to 0");
294294
clusterState = ClusterState.builder(clusterState)
295-
.routingTable(RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(0, "test").build())
296-
.metaData(MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(0, "test")).build();
295+
.routingTable(RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(0, new String[]{"test"}).build())
296+
.metaData(MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(0, new String[]{"test"})).build();
297297

298298
logger.info("add back node 1");
299299
clusterState = ClusterState.builder(clusterState).nodes(DiscoveryNodes.builder().add(

server/src/test/java/org/elasticsearch/cluster/routing/allocation/PreferPrimaryAllocationTests.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ public void testPreferPrimaryAllocationOverReplicas() {
6868
}
6969

7070
logger.info("increasing the number of replicas to 1, and perform a reroute (to get the replicas allocation going)");
71-
RoutingTable updatedRoutingTable = RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(1).build();
72-
metaData = MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(1).build();
71+
final String[] indices = {"test1", "test2"};
72+
RoutingTable updatedRoutingTable =
73+
RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(1, indices).build();
74+
metaData = MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(1, indices).build();
7375
clusterState = ClusterState.builder(clusterState).routingTable(updatedRoutingTable).metaData(metaData).build();
7476

7577
clusterState = strategy.reroute(clusterState, "reroute");

server/src/test/java/org/elasticsearch/cluster/routing/allocation/UpdateNumberOfReplicasTests.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ public void testUpdateNumberOfReplicas() {
9696

9797
logger.info("add another replica");
9898
routingNodes = clusterState.getRoutingNodes();
99-
RoutingTable updatedRoutingTable = RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(2).build();
100-
metaData = MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(2).build();
99+
final String[] indices = {"test"};
100+
RoutingTable updatedRoutingTable =
101+
RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(2, indices).build();
102+
metaData = MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(2, indices).build();
101103
clusterState = ClusterState.builder(clusterState).routingTable(updatedRoutingTable).metaData(metaData).build();
102104

103105
assertThat(clusterState.metaData().index("test").getNumberOfReplicas(), equalTo(2));
@@ -143,8 +145,8 @@ public void testUpdateNumberOfReplicas() {
143145

144146
logger.info("now remove a replica");
145147
routingNodes = clusterState.getRoutingNodes();
146-
updatedRoutingTable = RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(1).build();
147-
metaData = MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(1).build();
148+
updatedRoutingTable = RoutingTable.builder(clusterState.routingTable()).updateNumberOfReplicas(1, indices).build();
149+
metaData = MetaData.builder(clusterState.metaData()).updateNumberOfReplicas(1, indices).build();
148150
clusterState = ClusterState.builder(clusterState).routingTable(updatedRoutingTable).metaData(metaData).build();
149151

150152
assertThat(clusterState.metaData().index("test").getNumberOfReplicas(), equalTo(1));

server/src/test/java/org/elasticsearch/indices/settings/UpdateNumberOfReplicasIT.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121

2222
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
2323
import org.elasticsearch.action.search.SearchResponse;
24+
import org.elasticsearch.action.support.IndicesOptions;
2425
import org.elasticsearch.cluster.health.ClusterHealthStatus;
2526
import org.elasticsearch.cluster.metadata.IndexMetaData;
2627
import org.elasticsearch.common.Priority;
2728
import org.elasticsearch.common.settings.Settings;
2829
import org.elasticsearch.test.ESIntegTestCase;
2930

3031
import java.io.IOException;
32+
import java.util.EnumSet;
3133

3234
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
3335
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
@@ -274,4 +276,21 @@ public void testUpdateWithInvalidNumberOfReplicas() {
274276
assertEquals("Failed to parse value [" + value + "] for setting [index.number_of_replicas] must be >= 0", e.getMessage());
275277
}
276278
}
279+
280+
public void testUpdateNumberOfReplicasAllowNoIndices() {
281+
createIndex("test-index", Settings.builder().put("index.number_of_replicas", 0).build());
282+
final IndicesOptions options =
283+
new IndicesOptions(EnumSet.of(IndicesOptions.Option.ALLOW_NO_INDICES), EnumSet.of(IndicesOptions.WildcardStates.OPEN));
284+
assertAcked(client()
285+
.admin()
286+
.indices()
287+
.prepareUpdateSettings("non-existent-*")
288+
.setSettings(Settings.builder().put("index.number_of_replicas", 1))
289+
.setIndicesOptions(options)
290+
.get());
291+
final int numberOfReplicas = Integer.parseInt(
292+
client().admin().indices().prepareGetSettings("test-index").get().getSetting("test-index", "index.number_of_replicas"));
293+
assertThat(numberOfReplicas, equalTo(0));
294+
}
295+
277296
}

0 commit comments

Comments
 (0)