|
85 | 85 | import static org.elasticsearch.cluster.metadata.Metadata.DEFAULT_PROJECT_ID; |
86 | 86 | import static org.elasticsearch.cluster.routing.GlobalRoutingTableTestHelper.routingTable; |
87 | 87 | import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; |
| 88 | +import static org.elasticsearch.xpack.core.security.action.UpdateIndexMigrationVersionAction.MIGRATION_VERSION_CUSTOM_DATA_KEY; |
| 89 | +import static org.elasticsearch.xpack.core.security.action.UpdateIndexMigrationVersionAction.MIGRATION_VERSION_CUSTOM_KEY; |
88 | 90 | import static org.elasticsearch.xpack.security.support.SecurityIndexManager.FILE_SETTINGS_METADATA_NAMESPACE; |
89 | 91 | import static org.hamcrest.Matchers.aMapWithSize; |
90 | 92 | import static org.hamcrest.Matchers.contains; |
@@ -309,6 +311,60 @@ private ClusterChangedEvent event(ClusterState clusterState) { |
309 | 311 | return new ClusterChangedEvent("test-event", clusterState, EMPTY_CLUSTER_STATE); |
310 | 312 | } |
311 | 313 |
|
| 314 | + public void testStateChangeListenerIsCalledIfMigrationIsRequired() { |
| 315 | + final AtomicBoolean listenerCalled = new AtomicBoolean(false); |
| 316 | + final AtomicReference<ProjectId> projectIdRef = new AtomicReference<>(); |
| 317 | + final AtomicReference<IndexState> previousState = new AtomicReference<>(); |
| 318 | + final AtomicReference<IndexState> currentState = new AtomicReference<>(); |
| 319 | + final TriConsumer<ProjectId, IndexState, IndexState> listener = (projId, prevState, state) -> { |
| 320 | + projectIdRef.set(projId); |
| 321 | + previousState.set(prevState); |
| 322 | + currentState.set(state); |
| 323 | + listenerCalled.set(true); |
| 324 | + }; |
| 325 | + manager.addStateListener(listener); |
| 326 | + |
| 327 | + // index doesn't exist and now exists |
| 328 | + ClusterState.Builder clusterStateBuilder = createClusterState( |
| 329 | + TestRestrictedIndices.INTERNAL_SECURITY_MAIN_INDEX_7, |
| 330 | + SecuritySystemIndices.SECURITY_MAIN_ALIAS |
| 331 | + ); |
| 332 | + clusterStateBuilder = setMigrationVersion( |
| 333 | + clusterStateBuilder.build(), |
| 334 | + TestRestrictedIndices.INTERNAL_SECURITY_MAIN_INDEX_7, |
| 335 | + randomIntBetween(1, SecurityMigrations.highestMigrationVersion() - 1) |
| 336 | + ); |
| 337 | + |
| 338 | + final ClusterState clusterState = markShardsAvailable(clusterStateBuilder); |
| 339 | + manager.clusterChanged(event(clusterState)); |
| 340 | + |
| 341 | + assertThat(listenerCalled.get(), is(true)); |
| 342 | + |
| 343 | + for (int i = 0; i < 3; i++) { |
| 344 | + listenerCalled.set(false); |
| 345 | + ClusterChangedEvent event = new ClusterChangedEvent("same index state", clusterState, clusterState); |
| 346 | + manager.clusterChanged(event); |
| 347 | + |
| 348 | + assertThat(listenerCalled.get(), is(true)); |
| 349 | + assertThat(previousState.get(), equalTo(currentState.get())); |
| 350 | + } |
| 351 | + |
| 352 | + final var newClusterState = setMigrationVersion( |
| 353 | + clusterState, |
| 354 | + TestRestrictedIndices.INTERNAL_SECURITY_MAIN_INDEX_7, |
| 355 | + SecurityMigrations.highestMigrationVersion() |
| 356 | + ).build(); |
| 357 | + |
| 358 | + listenerCalled.set(false); |
| 359 | + manager.clusterChanged(new ClusterChangedEvent("modified index state", newClusterState, clusterState)); |
| 360 | + assertThat(listenerCalled.get(), is(true)); |
| 361 | + assertThat(previousState.get(), not(equalTo(currentState.get()))); |
| 362 | + |
| 363 | + listenerCalled.set(false); |
| 364 | + manager.clusterChanged(new ClusterChangedEvent("same index state", newClusterState, newClusterState)); |
| 365 | + assertThat(listenerCalled.get(), is(false)); |
| 366 | + } |
| 367 | + |
312 | 368 | public void testIndexHealthChangeListeners() { |
313 | 369 | final AtomicBoolean listenerCalled = new AtomicBoolean(false); |
314 | 370 | final AtomicReference<ProjectId> projectIdRef = new AtomicReference<>(); |
@@ -1123,6 +1179,22 @@ private static ProjectMetadata.Builder createProjectMetadata(ProjectId projectId |
1123 | 1179 | ); |
1124 | 1180 | } |
1125 | 1181 |
|
| 1182 | + private ClusterState.Builder setMigrationVersion(ClusterState clusterState, String indexName, Integer version) { |
| 1183 | + final ClusterState.Builder csBuilder = ClusterState.builder(clusterState); |
| 1184 | + clusterState.forEachProject(project -> { |
| 1185 | + final ProjectMetadata.Builder projectBuilder = ProjectMetadata.builder(project.metadata()); |
| 1186 | + final IndexMetadata.Builder indexBuilder = IndexMetadata.builder(project.metadata().index(indexName)); |
| 1187 | + if (version == null) { |
| 1188 | + indexBuilder.removeCustom(MIGRATION_VERSION_CUSTOM_KEY); |
| 1189 | + } else { |
| 1190 | + indexBuilder.putCustom(MIGRATION_VERSION_CUSTOM_KEY, Map.of(MIGRATION_VERSION_CUSTOM_DATA_KEY, Integer.toString(version))); |
| 1191 | + } |
| 1192 | + projectBuilder.put(indexBuilder); |
| 1193 | + csBuilder.putProjectMetadata(projectBuilder); |
| 1194 | + }); |
| 1195 | + return csBuilder; |
| 1196 | + } |
| 1197 | + |
1126 | 1198 | private ClusterState markShardsAvailable(ClusterState.Builder clusterStateBuilder) { |
1127 | 1199 | final ClusterState cs = clusterStateBuilder.build(); |
1128 | 1200 | final RoutingTable projectRouting = SecurityTestUtils.buildIndexRoutingTable( |
@@ -1159,7 +1231,6 @@ private static IndexMetadata.Builder getIndexMetadata( |
1159 | 1231 | if (mappings != null) { |
1160 | 1232 | indexMetadata.putMapping(mappings); |
1161 | 1233 | } |
1162 | | - |
1163 | 1234 | return indexMetadata; |
1164 | 1235 | } |
1165 | 1236 |
|
|
0 commit comments