|
14 | 14 | import org.elasticsearch.action.DocWriteResponse; |
15 | 15 | import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; |
16 | 16 | import org.elasticsearch.action.admin.indices.readonly.AddIndexBlockResponse; |
| 17 | +import org.elasticsearch.action.admin.indices.readonly.RemoveIndexBlockResponse; |
17 | 18 | import org.elasticsearch.action.index.IndexRequestBuilder; |
18 | 19 | import org.elasticsearch.action.support.ActiveShardCount; |
19 | 20 | import org.elasticsearch.action.support.PlainActionFuture; |
@@ -549,6 +550,143 @@ public static void disableIndexBlock(String index, APIBlock block) { |
549 | 550 | disableIndexBlock(index, block.settingName()); |
550 | 551 | } |
551 | 552 |
|
| 553 | + public void testRemoveBlockToMissingIndex() { |
| 554 | + IndexNotFoundException e = expectThrows( |
| 555 | + IndexNotFoundException.class, |
| 556 | + indicesAdmin().prepareRemoveBlock(randomAddableBlock(), "test") |
| 557 | + ); |
| 558 | + assertThat(e.getMessage(), is("no such index [test]")); |
| 559 | + } |
| 560 | + |
| 561 | + public void testRemoveBlockToOneMissingIndex() { |
| 562 | + createIndex("test1"); |
| 563 | + final IndexNotFoundException e = expectThrows( |
| 564 | + IndexNotFoundException.class, |
| 565 | + indicesAdmin().prepareRemoveBlock(randomAddableBlock(), "test1", "test2") |
| 566 | + ); |
| 567 | + assertThat(e.getMessage(), is("no such index [test2]")); |
| 568 | + } |
| 569 | + |
| 570 | + public void testRemoveBlockNoIndex() { |
| 571 | + final ActionRequestValidationException e = expectThrows( |
| 572 | + ActionRequestValidationException.class, |
| 573 | + indicesAdmin().prepareRemoveBlock(randomAddableBlock()) |
| 574 | + ); |
| 575 | + assertThat(e.getMessage(), containsString("index is missing")); |
| 576 | + } |
| 577 | + |
| 578 | + public void testRemoveBlockNullIndex() { |
| 579 | + expectThrows(NullPointerException.class, () -> indicesAdmin().prepareRemoveBlock(randomAddableBlock(), (String[]) null)); |
| 580 | + } |
| 581 | + |
| 582 | + public void testCannotRemoveReadOnlyAllowDeleteBlock() { |
| 583 | + createIndex("test1"); |
| 584 | + final ActionRequestValidationException e = expectThrows( |
| 585 | + ActionRequestValidationException.class, |
| 586 | + indicesAdmin().prepareRemoveBlock(APIBlock.READ_ONLY_ALLOW_DELETE, "test1") |
| 587 | + ); |
| 588 | + assertThat(e.getMessage(), containsString("read_only_allow_delete block is for internal use only")); |
| 589 | + } |
| 590 | + |
| 591 | + public void testRemoveIndexBlock() throws Exception { |
| 592 | + final String indexName = randomAlphaOfLength(10).toLowerCase(Locale.ROOT); |
| 593 | + createIndex(indexName); |
| 594 | + ensureGreen(indexName); |
| 595 | + |
| 596 | + final int nbDocs = randomIntBetween(0, 50); |
| 597 | + indexRandom( |
| 598 | + randomBoolean(), |
| 599 | + false, |
| 600 | + randomBoolean(), |
| 601 | + IntStream.range(0, nbDocs).mapToObj(i -> prepareIndex(indexName).setId(String.valueOf(i)).setSource("num", i)).collect(toList()) |
| 602 | + ); |
| 603 | + |
| 604 | + final APIBlock block = randomAddableBlock(); |
| 605 | + try { |
| 606 | + // First add the block |
| 607 | + AddIndexBlockResponse addResponse = indicesAdmin().prepareAddBlock(block, indexName).get(); |
| 608 | + assertTrue( |
| 609 | + "Add block [" + block + "] to index [" + indexName + "] not acknowledged: " + addResponse, |
| 610 | + addResponse.isAcknowledged() |
| 611 | + ); |
| 612 | + assertIndexHasBlock(block, indexName); |
| 613 | + |
| 614 | + // Then remove the block |
| 615 | + RemoveIndexBlockResponse removeResponse = indicesAdmin().prepareRemoveBlock(block, indexName).get(); |
| 616 | + assertTrue( |
| 617 | + "Remove block [" + block + "] from index [" + indexName + "] not acknowledged: " + removeResponse, |
| 618 | + removeResponse.isAcknowledged() |
| 619 | + ); |
| 620 | + assertIndexDoesNotHaveBlock(block, indexName); |
| 621 | + } finally { |
| 622 | + // Ensure cleanup |
| 623 | + disableIndexBlock(indexName, block); |
| 624 | + } |
| 625 | + |
| 626 | + indicesAdmin().prepareRefresh(indexName).get(); |
| 627 | + assertHitCount(prepareSearch(indexName).setSize(0), nbDocs); |
| 628 | + } |
| 629 | + |
| 630 | + public void testRemoveBlockIdempotent() throws Exception { |
| 631 | + final String indexName = randomAlphaOfLength(10).toLowerCase(Locale.ROOT); |
| 632 | + createIndex(indexName); |
| 633 | + ensureGreen(indexName); |
| 634 | + |
| 635 | + final APIBlock block = randomAddableBlock(); |
| 636 | + try { |
| 637 | + // First add the block |
| 638 | + assertAcked(indicesAdmin().prepareAddBlock(block, indexName)); |
| 639 | + assertIndexHasBlock(block, indexName); |
| 640 | + |
| 641 | + // Remove the block |
| 642 | + assertAcked(indicesAdmin().prepareRemoveBlock(block, indexName)); |
| 643 | + assertIndexDoesNotHaveBlock(block, indexName); |
| 644 | + |
| 645 | + // Second remove should be acked too (idempotent behavior) |
| 646 | + assertAcked(indicesAdmin().prepareRemoveBlock(block, indexName)); |
| 647 | + assertIndexDoesNotHaveBlock(block, indexName); |
| 648 | + } finally { |
| 649 | + disableIndexBlock(indexName, block); |
| 650 | + } |
| 651 | + } |
| 652 | + |
| 653 | + public void testRemoveBlockOneMissingIndexIgnoreMissing() throws Exception { |
| 654 | + createIndex("test1"); |
| 655 | + final APIBlock block = randomAddableBlock(); |
| 656 | + try { |
| 657 | + // First add the block to test1 |
| 658 | + assertAcked(indicesAdmin().prepareAddBlock(block, "test1")); |
| 659 | + assertIndexHasBlock(block, "test1"); |
| 660 | + |
| 661 | + // Remove from both test1 and test2 (missing), with lenient options |
| 662 | + assertBusy( |
| 663 | + () -> assertAcked(indicesAdmin().prepareRemoveBlock(block, "test1", "test2").setIndicesOptions(lenientExpandOpen())) |
| 664 | + ); |
| 665 | + assertIndexDoesNotHaveBlock(block, "test1"); |
| 666 | + } finally { |
| 667 | + disableIndexBlock("test1", block); |
| 668 | + } |
| 669 | + } |
| 670 | + |
| 671 | + static void assertIndexDoesNotHaveBlock(APIBlock block, final String... indices) { |
| 672 | + final ClusterState clusterState = clusterAdmin().prepareState(TEST_REQUEST_TIMEOUT).get().getState(); |
| 673 | + final ProjectId projectId = Metadata.DEFAULT_PROJECT_ID; |
| 674 | + for (String index : indices) { |
| 675 | + final IndexMetadata indexMetadata = clusterState.metadata().getProject(projectId).indices().get(index); |
| 676 | + final Settings indexSettings = indexMetadata.getSettings(); |
| 677 | + assertThat( |
| 678 | + "Index " + index + " should not have block setting [" + block.settingName() + "]", |
| 679 | + indexSettings.getAsBoolean(block.settingName(), false), |
| 680 | + is(false) |
| 681 | + ); |
| 682 | + assertThat( |
| 683 | + "Index " + index + " should not have block [" + block.getBlock() + "]", |
| 684 | + clusterState.blocks().hasIndexBlock(projectId, index, block.getBlock()), |
| 685 | + is(false) |
| 686 | + ); |
| 687 | + } |
| 688 | + } |
| 689 | + |
552 | 690 | /** |
553 | 691 | * The read-only-allow-delete block cannot be added via the add index block API; this method chooses randomly from the values that |
554 | 692 | * the add index block API does support. |
|
0 commit comments