20
20
package org .elasticsearch .action .admin .indices .rollover ;
21
21
22
22
import org .elasticsearch .Version ;
23
+ import org .elasticsearch .action .ActionListener ;
23
24
import org .elasticsearch .action .admin .indices .alias .IndicesAliasesClusterStateUpdateRequest ;
24
25
import org .elasticsearch .action .admin .indices .create .CreateIndexClusterStateUpdateRequest ;
25
26
import org .elasticsearch .action .admin .indices .stats .CommonStats ;
27
+ import org .elasticsearch .action .admin .indices .stats .IndexStats ;
28
+ import org .elasticsearch .action .admin .indices .stats .IndicesStatsRequestBuilder ;
26
29
import org .elasticsearch .action .admin .indices .stats .IndicesStatsResponse ;
30
+ import org .elasticsearch .action .support .ActionFilters ;
27
31
import org .elasticsearch .action .support .ActiveShardCount ;
32
+ import org .elasticsearch .action .support .PlainActionFuture ;
33
+ import org .elasticsearch .client .AdminClient ;
34
+ import org .elasticsearch .client .Client ;
35
+ import org .elasticsearch .client .IndicesAdminClient ;
36
+ import org .elasticsearch .cluster .ClusterName ;
37
+ import org .elasticsearch .cluster .ClusterState ;
28
38
import org .elasticsearch .cluster .metadata .AliasAction ;
29
39
import org .elasticsearch .cluster .metadata .AliasMetaData ;
30
40
import org .elasticsearch .cluster .metadata .IndexMetaData ;
31
41
import org .elasticsearch .cluster .metadata .IndexNameExpressionResolver ;
32
42
import org .elasticsearch .cluster .metadata .IndexTemplateMetaData ;
33
43
import org .elasticsearch .cluster .metadata .MetaData ;
44
+ import org .elasticsearch .cluster .metadata .MetaDataCreateIndexService ;
45
+ import org .elasticsearch .cluster .metadata .MetaDataIndexAliasesService ;
46
+ import org .elasticsearch .cluster .service .ClusterService ;
34
47
import org .elasticsearch .common .UUIDs ;
35
48
import org .elasticsearch .common .settings .Settings ;
36
49
import org .elasticsearch .common .unit .ByteSizeUnit ;
39
52
import org .elasticsearch .common .util .set .Sets ;
40
53
import org .elasticsearch .index .shard .DocsStats ;
41
54
import org .elasticsearch .test .ESTestCase ;
55
+ import org .elasticsearch .threadpool .ThreadPool ;
56
+ import org .elasticsearch .transport .TransportService ;
42
57
import org .mockito .ArgumentCaptor ;
43
58
44
59
import java .util .Arrays ;
60
+ import java .util .HashMap ;
45
61
import java .util .List ;
46
62
import java .util .Locale ;
47
63
import java .util .Map ;
51
67
import static org .hamcrest .Matchers .containsString ;
52
68
import static org .hamcrest .Matchers .equalTo ;
53
69
import static org .hamcrest .Matchers .hasSize ;
70
+ import static org .hamcrest .Matchers .is ;
54
71
import static org .mockito .Matchers .any ;
72
+ import static org .mockito .Mockito .doAnswer ;
55
73
import static org .mockito .Mockito .mock ;
56
74
import static org .mockito .Mockito .verify ;
57
75
import static org .mockito .Mockito .when ;
@@ -64,7 +82,9 @@ public void testDocStatsSelectionFromPrimariesOnly() {
64
82
long docsInShards = 200 ;
65
83
66
84
final Condition <?> condition = createTestCondition ();
67
- evaluateConditions (Sets .newHashSet (condition ), createMetaData (), createIndicesStatResponse (docsInShards , docsInPrimaryShards ));
85
+ String indexName = randomAlphaOfLengthBetween (5 , 7 );
86
+ evaluateConditions (Sets .newHashSet (condition ), createMetaData (indexName ),
87
+ createIndicesStatResponse (indexName , docsInShards , docsInPrimaryShards ));
68
88
final ArgumentCaptor <Condition .Stats > argument = ArgumentCaptor .forClass (Condition .Stats .class );
69
89
verify (condition ).evaluate (argument .capture ());
70
90
@@ -286,36 +306,150 @@ public void testRejectDuplicateAlias() {
286
306
.patterns (Arrays .asList ("foo-*" , "bar-*" ))
287
307
.putAlias (AliasMetaData .builder ("foo-write" )).putAlias (AliasMetaData .builder ("bar-write" ).writeIndex (randomBoolean ()))
288
308
.build ();
289
- final MetaData metaData = MetaData .builder ().put (createMetaData (), false ).put (template ).build ();
309
+ final MetaData metaData = MetaData .builder ().put (createMetaData (randomAlphaOfLengthBetween ( 5 , 7 ) ), false ).put (template ).build ();
290
310
String indexName = randomFrom ("foo-123" , "bar-xyz" );
291
311
String aliasName = randomFrom ("foo-write" , "bar-write" );
292
312
final IllegalArgumentException ex = expectThrows (IllegalArgumentException .class ,
293
313
() -> TransportRolloverAction .checkNoDuplicatedAliasInIndexTemplate (metaData , indexName , aliasName ));
294
314
assertThat (ex .getMessage (), containsString ("index template [test-template]" ));
295
315
}
296
316
297
- private IndicesStatsResponse createIndicesStatResponse (long totalDocs , long primaryDocs ) {
317
+ public void testConditionEvaluationWhenAliasToWriteAndReadIndicesConsidersOnlyPrimariesFromWriteIndex () {
318
+ final TransportService mockTransportService = mock (TransportService .class );
319
+ final ClusterService mockClusterService = mock (ClusterService .class );
320
+ final ThreadPool mockThreadPool = mock (ThreadPool .class );
321
+ final MetaDataCreateIndexService mockCreateIndexService = mock (MetaDataCreateIndexService .class );
322
+ final IndexNameExpressionResolver mockIndexNameExpressionResolver = mock (IndexNameExpressionResolver .class );
323
+ when (mockIndexNameExpressionResolver .resolveDateMathExpression (any ())).thenReturn ("logs-index-000003" );
324
+ final ActionFilters mockActionFilters = mock (ActionFilters .class );
325
+ final MetaDataIndexAliasesService mdIndexAliasesService = mock (MetaDataIndexAliasesService .class );
326
+
327
+ final Client mockClient = mock (Client .class );
328
+ final AdminClient mockAdminClient = mock (AdminClient .class );
329
+ final IndicesAdminClient mockIndicesAdminClient = mock (IndicesAdminClient .class );
330
+ when (mockClient .admin ()).thenReturn (mockAdminClient );
331
+ when (mockAdminClient .indices ()).thenReturn (mockIndicesAdminClient );
332
+
333
+ final IndicesStatsRequestBuilder mockIndicesStatsBuilder = mock (IndicesStatsRequestBuilder .class );
334
+ when (mockIndicesAdminClient .prepareStats (any ())).thenReturn (mockIndicesStatsBuilder );
335
+ final Map <String , IndexStats > indexStats = new HashMap <>();
336
+ int total = randomIntBetween (500 , 1000 );
337
+ indexStats .put ("logs-index-000001" , createIndexStats (200L , total ));
338
+ indexStats .put ("logs-index-000002" , createIndexStats (300L , total ));
339
+ final IndicesStatsResponse statsResponse = createAliasToMultipleIndicesStatsResponse (indexStats );
340
+ when (mockIndicesStatsBuilder .clear ()).thenReturn (mockIndicesStatsBuilder );
341
+ when (mockIndicesStatsBuilder .setDocs (true )).thenReturn (mockIndicesStatsBuilder );
342
+
343
+ assert statsResponse .getPrimaries ().getDocs ().getCount () == 500L ;
344
+ assert statsResponse .getTotal ().getDocs ().getCount () == (total + total );
345
+
346
+ doAnswer (invocation -> {
347
+ Object [] args = invocation .getArguments ();
348
+ assert args .length == 1 ;
349
+ ActionListener <IndicesStatsResponse > listener = (ActionListener <IndicesStatsResponse >) args [0 ];
350
+ listener .onResponse (statsResponse );
351
+ return null ;
352
+ }).when (mockIndicesStatsBuilder ).execute (any (ActionListener .class ));
353
+
354
+ final IndexMetaData .Builder indexMetaData = IndexMetaData .builder ("logs-index-000001" )
355
+ .putAlias (AliasMetaData .builder ("logs-alias" ).writeIndex (false ).build ()).settings (settings (Version .CURRENT ))
356
+ .numberOfShards (1 ).numberOfReplicas (1 );
357
+ final IndexMetaData .Builder indexMetaData2 = IndexMetaData .builder ("logs-index-000002" )
358
+ .putAlias (AliasMetaData .builder ("logs-alias" ).writeIndex (true ).build ()).settings (settings (Version .CURRENT ))
359
+ .numberOfShards (1 ).numberOfReplicas (1 );
360
+ final ClusterState stateBefore = ClusterState .builder (ClusterName .DEFAULT )
361
+ .metaData (MetaData .builder ().put (indexMetaData ).put (indexMetaData2 )).build ();
362
+
363
+ final TransportRolloverAction transportRolloverAction = new TransportRolloverAction (mockTransportService , mockClusterService ,
364
+ mockThreadPool , mockCreateIndexService , mockActionFilters , mockIndexNameExpressionResolver , mdIndexAliasesService ,
365
+ mockClient );
366
+
367
+ // For given alias, verify that condition evaluation fails when the condition doc count is greater than the primaries doc count
368
+ // (primaries from only write index is considered)
369
+ PlainActionFuture <RolloverResponse > future = new PlainActionFuture <>();
370
+ RolloverRequest rolloverRequest = new RolloverRequest ("logs-alias" , "logs-index-000003" );
371
+ rolloverRequest .addMaxIndexDocsCondition (500L );
372
+ rolloverRequest .dryRun (true );
373
+ transportRolloverAction .masterOperation (rolloverRequest , stateBefore , future );
374
+
375
+ RolloverResponse response = future .actionGet ();
376
+ assertThat (response .getOldIndex (), equalTo ("logs-index-000002" ));
377
+ assertThat (response .getNewIndex (), equalTo ("logs-index-000003" ));
378
+ assertThat (response .isDryRun (), equalTo (true ));
379
+ assertThat (response .isRolledOver (), equalTo (false ));
380
+ assertThat (response .getConditionStatus ().size (), equalTo (1 ));
381
+ assertThat (response .getConditionStatus ().get ("[max_docs: 500]" ), is (false ));
382
+
383
+ // For given alias, verify that the condition evaluation is successful when condition doc count is less than the primaries doc count
384
+ // (primaries from only write index is considered)
385
+ future = new PlainActionFuture <>();
386
+ rolloverRequest = new RolloverRequest ("logs-alias" , "logs-index-000003" );
387
+ rolloverRequest .addMaxIndexDocsCondition (300L );
388
+ rolloverRequest .dryRun (true );
389
+ transportRolloverAction .masterOperation (rolloverRequest , stateBefore , future );
390
+
391
+ response = future .actionGet ();
392
+ assertThat (response .getOldIndex (), equalTo ("logs-index-000002" ));
393
+ assertThat (response .getNewIndex (), equalTo ("logs-index-000003" ));
394
+ assertThat (response .isDryRun (), equalTo (true ));
395
+ assertThat (response .isRolledOver (), equalTo (false ));
396
+ assertThat (response .getConditionStatus ().size (), equalTo (1 ));
397
+ assertThat (response .getConditionStatus ().get ("[max_docs: 300]" ), is (true ));
398
+ }
399
+
400
+ private IndicesStatsResponse createIndicesStatResponse (String indexName , long totalDocs , long primariesDocs ) {
298
401
final CommonStats primaryStats = mock (CommonStats .class );
299
- when (primaryStats .getDocs ()).thenReturn (new DocsStats (primaryDocs , 0 , between (1 , 10000 )));
402
+ when (primaryStats .getDocs ()).thenReturn (new DocsStats (primariesDocs , 0 , between (1 , 10000 )));
300
403
301
404
final CommonStats totalStats = mock (CommonStats .class );
302
405
when (totalStats .getDocs ()).thenReturn (new DocsStats (totalDocs , 0 , between (1 , 10000 )));
303
406
304
407
final IndicesStatsResponse response = mock (IndicesStatsResponse .class );
305
408
when (response .getPrimaries ()).thenReturn (primaryStats );
306
409
when (response .getTotal ()).thenReturn (totalStats );
410
+ final IndexStats indexStats = mock (IndexStats .class );
411
+ when (response .getIndex (indexName )).thenReturn (indexStats );
412
+ when (indexStats .getPrimaries ()).thenReturn (primaryStats );
413
+ when (indexStats .getTotal ()).thenReturn (totalStats );
414
+ return response ;
415
+ }
416
+
417
+ private IndicesStatsResponse createAliasToMultipleIndicesStatsResponse (Map <String , IndexStats > indexStats ) {
418
+ final IndicesStatsResponse response = mock (IndicesStatsResponse .class );
419
+ final CommonStats primariesStats = new CommonStats ();
420
+ final CommonStats totalStats = new CommonStats ();
421
+ for (String indexName : indexStats .keySet ()) {
422
+ when (response .getIndex (indexName )).thenReturn (indexStats .get (indexName ));
423
+ primariesStats .add (indexStats .get (indexName ).getPrimaries ());
424
+ totalStats .add (indexStats .get (indexName ).getTotal ());
425
+ }
307
426
427
+ when (response .getPrimaries ()).thenReturn (primariesStats );
428
+ when (response .getTotal ()).thenReturn (totalStats );
308
429
return response ;
309
430
}
310
431
311
- private static IndexMetaData createMetaData () {
432
+ private IndexStats createIndexStats (long primaries , long total ) {
433
+ final CommonStats primariesCommonStats = mock (CommonStats .class );
434
+ when (primariesCommonStats .getDocs ()).thenReturn (new DocsStats (primaries , 0 , between (1 , 10000 )));
435
+
436
+ final CommonStats totalCommonStats = mock (CommonStats .class );
437
+ when (totalCommonStats .getDocs ()).thenReturn (new DocsStats (total , 0 , between (1 , 10000 )));
438
+
439
+ IndexStats indexStats = mock (IndexStats .class );
440
+ when (indexStats .getPrimaries ()).thenReturn (primariesCommonStats );
441
+ when (indexStats .getTotal ()).thenReturn (totalCommonStats );
442
+ return indexStats ;
443
+ }
444
+
445
+ private static IndexMetaData createMetaData (String indexName ) {
312
446
final Settings settings = Settings .builder ()
313
447
.put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT )
314
448
.put (IndexMetaData .SETTING_INDEX_UUID , UUIDs .randomBase64UUID ())
315
449
.put (IndexMetaData .SETTING_NUMBER_OF_SHARDS , 1 )
316
450
.put (IndexMetaData .SETTING_NUMBER_OF_REPLICAS , 0 )
317
451
.build ();
318
- return IndexMetaData .builder (randomAlphaOfLength ( 10 ) )
452
+ return IndexMetaData .builder (indexName )
319
453
.creationDate (System .currentTimeMillis () - TimeValue .timeValueHours (3 ).getMillis ())
320
454
.settings (settings )
321
455
.build ();
0 commit comments