|
15 | 15 | import java.io.IOException;
|
16 | 16 | import java.nio.file.Path;
|
17 | 17 | import java.time.Instant;
|
| 18 | +import java.util.Collections; |
18 | 19 | import java.util.Set;
|
19 | 20 | import java.util.concurrent.TimeoutException;
|
20 | 21 |
|
|
34 | 35 | import org.opensearch.cluster.ClusterChangedEvent;
|
35 | 36 | import org.opensearch.cluster.ClusterState;
|
36 | 37 | import org.opensearch.cluster.ClusterStateUpdateTask;
|
| 38 | +import org.opensearch.cluster.RestoreInProgress; |
37 | 39 | import org.opensearch.cluster.block.ClusterBlocks;
|
38 | 40 | import org.opensearch.cluster.metadata.IndexMetadata;
|
39 | 41 | import org.opensearch.cluster.metadata.MappingMetadata;
|
40 | 42 | import org.opensearch.cluster.metadata.Metadata;
|
41 | 43 | import org.opensearch.cluster.node.DiscoveryNode;
|
42 | 44 | import org.opensearch.cluster.node.DiscoveryNodes;
|
| 45 | +import org.opensearch.cluster.routing.ShardRouting; |
43 | 46 | import org.opensearch.cluster.service.ClusterService;
|
44 | 47 | import org.opensearch.common.Priority;
|
45 | 48 | import org.opensearch.common.settings.Settings;
|
46 | 49 | import org.opensearch.core.action.ActionListener;
|
| 50 | +import org.opensearch.core.index.Index; |
| 51 | +import org.opensearch.core.index.shard.ShardId; |
47 | 52 | import org.opensearch.core.rest.RestStatus;
|
| 53 | +import org.opensearch.index.shard.IndexShard; |
48 | 54 | import org.opensearch.security.DefaultObjectMapper;
|
49 | 55 | import org.opensearch.security.auditlog.AuditLog;
|
50 | 56 | import org.opensearch.security.securityconf.DynamicConfigFactory;
|
|
63 | 69 |
|
64 | 70 | import org.mockito.ArgumentCaptor;
|
65 | 71 | import org.mockito.Mock;
|
| 72 | +import org.mockito.Mockito; |
66 | 73 | import org.mockito.junit.MockitoJUnitRunner;
|
67 | 74 | import org.mockito.stubbing.OngoingStubbing;
|
68 | 75 |
|
|
82 | 89 | import static org.mockito.Mockito.anyString;
|
83 | 90 | import static org.mockito.Mockito.doAnswer;
|
84 | 91 | import static org.mockito.Mockito.doCallRealMethod;
|
| 92 | +import static org.mockito.Mockito.doReturn; |
85 | 93 | import static org.mockito.Mockito.mock;
|
86 | 94 | import static org.mockito.Mockito.never;
|
87 | 95 | import static org.mockito.Mockito.reset;
|
| 96 | +import static org.mockito.Mockito.spy; |
88 | 97 | import static org.mockito.Mockito.times;
|
89 | 98 | import static org.mockito.Mockito.verify;
|
90 | 99 | import static org.mockito.Mockito.verifyNoMoreInteractions;
|
@@ -569,6 +578,47 @@ public void getConfigurationsFromIndex_SecurityIndexNotInitiallyReady() throws I
|
569 | 578 | assertThat(result.size(), is(CType.values().size()));
|
570 | 579 | }
|
571 | 580 |
|
| 581 | + @Test |
| 582 | + public void afterIndexShardStarted_whenSecurityIndexUpdated() throws InterruptedException, TimeoutException { |
| 583 | + Settings settings = Settings.builder().build(); |
| 584 | + ConfigurationRepository configurationRepository = spy(createConfigurationRepository(settings)); |
| 585 | + IndexShard indexShard = mock(IndexShard.class); |
| 586 | + ShardRouting shardRouting = mock(ShardRouting.class); |
| 587 | + ShardId shardId = mock(ShardId.class); |
| 588 | + Index index = mock(Index.class); |
| 589 | + ClusterState mockClusterState = mock(ClusterState.class); |
| 590 | + RestoreInProgress mockRestore = mock(RestoreInProgress.class); |
| 591 | + RestoreInProgress.Entry mockEntry = mock(RestoreInProgress.Entry.class); |
| 592 | + |
| 593 | + // Setup mock behavior |
| 594 | + when(indexShard.shardId()).thenReturn(shardId); |
| 595 | + when(shardId.getIndex()).thenReturn(index); |
| 596 | + when(index.getName()).thenReturn(ConfigConstants.OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX); |
| 597 | + when(indexShard.routingEntry()).thenReturn(shardRouting); |
| 598 | + when(clusterService.state()).thenReturn(mockClusterState); |
| 599 | + when(mockClusterState.custom(RestoreInProgress.TYPE)).thenReturn(mockRestore); |
| 600 | + |
| 601 | + // when replica shard updated |
| 602 | + when(shardRouting.primary()).thenReturn(false); |
| 603 | + configurationRepository.afterIndexShardStarted(indexShard); |
| 604 | + verify(configurationRepository, never()).reloadConfiguration(any()); |
| 605 | + |
| 606 | + // when primary shard updated |
| 607 | + doReturn(true).when(configurationRepository).reloadConfiguration(any()); |
| 608 | + when(shardRouting.primary()).thenReturn(true); |
| 609 | + when(mockRestore.iterator()).thenReturn(Collections.singletonList(mockEntry).iterator()); |
| 610 | + when(mockEntry.indices()).thenReturn(Collections.singletonList(ConfigConstants.OPENDISTRO_SECURITY_DEFAULT_CONFIG_INDEX)); |
| 611 | + configurationRepository.afterIndexShardStarted(indexShard); |
| 612 | + verify(configurationRepository).reloadConfiguration(CType.values()); |
| 613 | + |
| 614 | + // When there is error in checking if restored from snapshot |
| 615 | + Mockito.reset(configurationRepository); |
| 616 | + when(clusterService.state()).thenThrow(new RuntimeException("ClusterState exception")); |
| 617 | + when(shardRouting.primary()).thenReturn(true); |
| 618 | + configurationRepository.afterIndexShardStarted(indexShard); |
| 619 | + verify(configurationRepository, never()).reloadConfiguration(any()); |
| 620 | + } |
| 621 | + |
572 | 622 | void assertClusterState(final ArgumentCaptor<ClusterStateUpdateTask> clusterStateUpdateTaskCaptor) throws Exception {
|
573 | 623 | final var initializedStateUpdate = clusterStateUpdateTaskCaptor.getValue();
|
574 | 624 | assertThat(initializedStateUpdate.priority(), is(Priority.IMMEDIATE));
|
|
0 commit comments