diff --git a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java index d2c86e69fbd..5753f17c351 100644 --- a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java +++ b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/CcrLicenseChecker.java @@ -244,6 +244,11 @@ public final class CcrLicenseChecker { String leaderIndex = leaderIndexMetaData.getIndex().getName(); CheckedConsumer indicesStatsHandler = indicesStatsResponse -> { IndexStats indexStats = indicesStatsResponse.getIndices().get(leaderIndex); + if (indexStats == null) { + onFailure.accept(new IllegalArgumentException("no index stats available for the leader index")); + return; + } + String[] historyUUIDs = new String[leaderIndexMetaData.getNumberOfShards()]; for (IndexShardStats indexShardStats : indexStats) { for (ShardStats shardStats : indexShardStats) { diff --git a/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/IndexFollowingIT.java b/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/IndexFollowingIT.java index 8f42787010c..45360041c4d 100644 --- a/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/IndexFollowingIT.java +++ b/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/IndexFollowingIT.java @@ -9,8 +9,11 @@ package org.elasticsearch.xpack.ccr; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse; +import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; +import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; import org.elasticsearch.action.admin.indices.stats.ShardStats; @@ -19,6 +22,7 @@ import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; @@ -552,6 +556,35 @@ public class IndexFollowingIT extends CcrIntegTestCase { assertThat(e.getMessage(), equalTo("unknown cluster alias [another_cluster]")); } + public void testLeaderIndexRed() throws Exception { + try { + ClusterUpdateSettingsRequest updateSettingsRequest = new ClusterUpdateSettingsRequest(); + updateSettingsRequest.transientSettings(Settings.builder().put("cluster.routing.allocation.enable", "none")); + assertAcked(leaderClient().admin().cluster().updateSettings(updateSettingsRequest).actionGet()); + assertAcked(leaderClient().admin().indices().prepareCreate("index1") + .setWaitForActiveShards(ActiveShardCount.NONE) + .setSettings(Settings.builder() + .put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true) + .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) + .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) + .build())); + + final PutFollowAction.Request followRequest = putFollow("index1", "index2"); + Exception e = expectThrows(IllegalArgumentException.class, + () -> followerClient().execute(PutFollowAction.INSTANCE, followRequest).actionGet()); + assertThat(e.getMessage(), equalTo("no index stats available for the leader index")); + + IndicesExistsResponse existsResponse = followerClient().admin().indices().exists(new IndicesExistsRequest("index2")) + .actionGet(); + assertThat(existsResponse.isExists(), is(false)); + } finally { + // Always unset allocation enable setting to avoid other assertions from failing too when this test fails: + ClusterUpdateSettingsRequest updateSettingsRequest = new ClusterUpdateSettingsRequest(); + updateSettingsRequest.transientSettings(Settings.builder().put("cluster.routing.allocation.enable", (String) null)); + assertAcked(leaderClient().admin().cluster().updateSettings(updateSettingsRequest).actionGet()); + } + } + private CheckedRunnable assertTask(final int numberOfPrimaryShards, final Map numDocsPerShard) { return () -> { final ClusterState clusterState = followerClient().admin().cluster().prepareState().get().getState();