Skip to content

Commit 60b1e1b

Browse files
authored
[7.2] Prevent NullPointerException in TransportRolloverAction (#43353) (#43398)
It's possible for the passed in `IndexMetaData` to be null (for instance, cluster state passed in does not have the index in its metadata) which in turn can cause a `NullPointerException` when evaluating the conditions for an index. This commit adds null protection and unit tests for this case. Resolves #43296
1 parent d8ff124 commit 60b1e1b

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import org.elasticsearch.cluster.metadata.MetaDataIndexAliasesService;
4545
import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService;
4646
import org.elasticsearch.cluster.service.ClusterService;
47+
import org.elasticsearch.common.Nullable;
4748
import org.elasticsearch.common.inject.Inject;
4849
import org.elasticsearch.common.unit.ByteSizeValue;
4950
import org.elasticsearch.index.shard.DocsStats;
@@ -55,6 +56,7 @@
5556
import java.util.List;
5657
import java.util.Locale;
5758
import java.util.Map;
59+
import java.util.Optional;
5860
import java.util.regex.Pattern;
5961
import java.util.stream.Collectors;
6062

@@ -238,7 +240,11 @@ static String generateRolloverIndexName(String sourceIndexName, IndexNameExpress
238240
}
239241

240242
static Map<String, Boolean> evaluateConditions(final Collection<Condition<?>> conditions,
241-
final DocsStats docsStats, final IndexMetaData metaData) {
243+
@Nullable final DocsStats docsStats,
244+
@Nullable final IndexMetaData metaData) {
245+
if (metaData == null) {
246+
return conditions.stream().collect(Collectors.toMap(Condition::toString, cond -> false));
247+
}
242248
final long numDocs = docsStats == null ? 0 : docsStats.getCount();
243249
final long indexSize = docsStats == null ? 0 : docsStats.getTotalSizeInBytes();
244250
final Condition.Stats stats = new Condition.Stats(numDocs, metaData.getCreationDate(), new ByteSizeValue(indexSize));
@@ -247,9 +253,18 @@ static Map<String, Boolean> evaluateConditions(final Collection<Condition<?>> co
247253
.collect(Collectors.toMap(result -> result.condition.toString(), result -> result.matched));
248254
}
249255

250-
static Map<String, Boolean> evaluateConditions(final Collection<Condition<?>> conditions, final IndexMetaData metaData,
251-
final IndicesStatsResponse statsResponse) {
252-
return evaluateConditions(conditions, statsResponse.getIndex(metaData.getIndex().getName()).getPrimaries().getDocs(), metaData);
256+
static Map<String, Boolean> evaluateConditions(final Collection<Condition<?>> conditions,
257+
@Nullable final IndexMetaData metaData,
258+
@Nullable final IndicesStatsResponse statsResponse) {
259+
if (metaData == null) {
260+
return conditions.stream().collect(Collectors.toMap(Condition::toString, cond -> false));
261+
} else {
262+
final DocsStats docsStats = Optional.ofNullable(statsResponse)
263+
.map(stats -> stats.getIndex(metaData.getIndex().getName()))
264+
.map(indexStats -> indexStats.getPrimaries().getDocs())
265+
.orElse(null);
266+
return evaluateConditions(conditions, docsStats, metaData);
267+
}
253268
}
254269

255270
static void validate(MetaData metaData, RolloverRequest request) {

server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.elasticsearch.common.unit.TimeValue;
5252
import org.elasticsearch.common.util.set.Sets;
5353
import org.elasticsearch.index.shard.DocsStats;
54+
import org.elasticsearch.rest.action.cat.RestIndicesActionTests;
5455
import org.elasticsearch.test.ESTestCase;
5556
import org.elasticsearch.threadpool.ThreadPool;
5657
import org.elasticsearch.transport.TransportService;
@@ -165,6 +166,35 @@ public void testEvaluateWithoutDocStats() {
165166
}
166167
}
167168

169+
public void testEvaluateWithoutMetaData() {
170+
MaxDocsCondition maxDocsCondition = new MaxDocsCondition(100L);
171+
MaxAgeCondition maxAgeCondition = new MaxAgeCondition(TimeValue.timeValueHours(2));
172+
MaxSizeCondition maxSizeCondition = new MaxSizeCondition(new ByteSizeValue(randomIntBetween(10, 100), ByteSizeUnit.MB));
173+
174+
long matchMaxDocs = randomIntBetween(100, 1000);
175+
final Set<Condition<?>> conditions = Sets.newHashSet(maxDocsCondition, maxAgeCondition, maxSizeCondition);
176+
Map<String, Boolean> results = evaluateConditions(conditions,
177+
new DocsStats(matchMaxDocs, 0L, ByteSizeUnit.MB.toBytes(120)), null);
178+
assertThat(results.size(), equalTo(3));
179+
results.forEach((k, v) -> assertFalse(v));
180+
181+
final Settings settings = Settings.builder()
182+
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
183+
.put(IndexMetaData.SETTING_INDEX_UUID, UUIDs.randomBase64UUID())
184+
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, randomIntBetween(1, 1000))
185+
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, randomInt(10))
186+
.build();
187+
188+
final IndexMetaData metaData = IndexMetaData.builder(randomAlphaOfLength(10))
189+
.creationDate(System.currentTimeMillis() - TimeValue.timeValueHours(randomIntBetween(5, 10)).getMillis())
190+
.settings(settings)
191+
.build();
192+
IndicesStatsResponse indicesStats = RestIndicesActionTests.randomIndicesStatsResponse(new IndexMetaData[]{metaData});
193+
Map<String, Boolean> results2 = evaluateConditions(conditions, null, indicesStats);
194+
assertThat(results2.size(), equalTo(3));
195+
results2.forEach((k, v) -> assertFalse(v));
196+
}
197+
168198
public void testCreateUpdateAliasRequest() {
169199
String sourceAlias = randomAlphaOfLength(10);
170200
String sourceIndex = randomAlphaOfLength(10);

server/src/test/java/org/elasticsearch/rest/action/cat/RestIndicesActionTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public void testBuildTable() {
151151
}
152152
}
153153

154-
private IndicesStatsResponse randomIndicesStatsResponse(final IndexMetaData[] indices) {
154+
public static IndicesStatsResponse randomIndicesStatsResponse(final IndexMetaData[] indices) {
155155
List<ShardStats> shardStats = new ArrayList<>();
156156
for (final IndexMetaData index : indices) {
157157
int numShards = randomIntBetween(1, 3);

0 commit comments

Comments
 (0)