2525import org .elasticsearch .action .support .ActiveShardCount ;
2626import org .elasticsearch .client .internal .Client ;
2727import org .elasticsearch .cluster .ClusterState ;
28+ import org .elasticsearch .cluster .ClusterStateTaskExecutor ;
29+ import org .elasticsearch .cluster .ClusterStateUpdateTask ;
2830import org .elasticsearch .cluster .metadata .IndexMetadata ;
2931import org .elasticsearch .cluster .metadata .Metadata ;
3032import org .elasticsearch .cluster .service .ClusterService ;
3739import org .elasticsearch .reindex .ReindexPlugin ;
3840import org .elasticsearch .test .ESIntegTestCase ;
3941import org .elasticsearch .upgrades .FeatureMigrationResults ;
42+ import org .elasticsearch .upgrades .SingleFeatureMigrationResult ;
4043import org .elasticsearch .xcontent .XContentBuilder ;
4144import org .elasticsearch .xcontent .json .JsonXContent ;
4245
5053import java .util .Map ;
5154import java .util .Optional ;
5255import java .util .Set ;
56+ import java .util .concurrent .CountDownLatch ;
57+ import java .util .concurrent .TimeUnit ;
5358import java .util .concurrent .atomic .AtomicReference ;
5459import java .util .function .BiConsumer ;
5560import java .util .function .Function ;
@@ -267,6 +272,67 @@ public void testMigrateIndexWithWriteBlock() throws Exception {
267272 });
268273 }
269274
275+ public void testMigrationWillRunAfterError () throws Exception {
276+ createSystemIndexForDescriptor (INTERNAL_MANAGED );
277+
278+ TestPlugin .preMigrationHook .set ((state ) -> Collections .emptyMap ());
279+ TestPlugin .postMigrationHook .set ((state , metadata ) -> {});
280+
281+ ensureGreen ();
282+
283+ SetOnce <Exception > failure = new SetOnce <>();
284+ CountDownLatch clusterStateUpdated = new CountDownLatch (1 );
285+ internalCluster ().getCurrentMasterNodeInstance (ClusterService .class )
286+ .submitStateUpdateTask (this .getTestName (), new ClusterStateUpdateTask () {
287+ @ Override
288+ public ClusterState execute (ClusterState currentState ) throws Exception {
289+ FeatureMigrationResults newResults = new FeatureMigrationResults (
290+ Collections .singletonMap (
291+ FEATURE_NAME ,
292+ SingleFeatureMigrationResult .failure (INTERNAL_MANAGED_INDEX_NAME , new RuntimeException ("it failed :(" ))
293+ )
294+ );
295+ Metadata newMetadata = Metadata .builder (currentState .metadata ())
296+ .putCustom (FeatureMigrationResults .TYPE , newResults )
297+ .build ();
298+ return ClusterState .builder (currentState ).metadata (newMetadata ).build ();
299+ }
300+
301+ @ Override
302+ public void clusterStateProcessed (ClusterState oldState , ClusterState newState ) {
303+ clusterStateUpdated .countDown ();
304+ }
305+
306+ @ Override
307+ public void onFailure (Exception e ) {
308+ failure .set (e );
309+ clusterStateUpdated .countDown ();
310+ }
311+ }, ClusterStateTaskExecutor .unbatched ());
312+
313+ clusterStateUpdated .await (10 , TimeUnit .SECONDS ); // Should be basically instantaneous
314+ if (failure .get () != null ) {
315+ logger .error ("cluster state update to inject migration failure state did not succeed" , failure .get ());
316+ fail ("cluster state update failed, see log for details" );
317+ }
318+
319+ PostFeatureUpgradeRequest migrationRequest = new PostFeatureUpgradeRequest ();
320+ PostFeatureUpgradeResponse migrationResponse = client ().execute (PostFeatureUpgradeAction .INSTANCE , migrationRequest ).get ();
321+ // Make sure we actually started the migration
322+ assertTrue (
323+ "could not find [" + FEATURE_NAME + "] in response: " + Strings .toString (migrationResponse ),
324+ migrationResponse .getFeatures ().stream ().anyMatch (feature -> feature .getFeatureName ().equals (FEATURE_NAME ))
325+ );
326+
327+ // Now wait for the migration to finish (otherwise the test infra explodes)
328+ assertBusy (() -> {
329+ GetFeatureUpgradeStatusRequest getStatusRequest = new GetFeatureUpgradeStatusRequest ();
330+ GetFeatureUpgradeStatusResponse statusResp = client ().execute (GetFeatureUpgradeStatusAction .INSTANCE , getStatusRequest ).get ();
331+ logger .info (Strings .toString (statusResp ));
332+ assertThat (statusResp .getUpgradeStatus (), equalTo (GetFeatureUpgradeStatusResponse .UpgradeStatus .NO_MIGRATION_NEEDED ));
333+ });
334+ }
335+
270336 public void assertIndexHasCorrectProperties (
271337 Metadata metadata ,
272338 String indexName ,
@@ -344,6 +410,7 @@ public void createSystemIndexForDescriptor(SystemIndexDescriptor descriptor) thr
344410 static final String FEATURE_NAME = "A-test-feature" ; // Sorts alphabetically before the feature from MultiFeatureMigrationIT
345411 static final String ORIGIN = FeatureMigrationIT .class .getSimpleName ();
346412 static final String FlAG_SETTING_KEY = IndexMetadata .INDEX_PRIORITY_SETTING .getKey ();
413+ static final String INTERNAL_MANAGED_INDEX_NAME = ".int-man-old" ;
347414 static final int INDEX_DOC_COUNT = 100 ; // arbitrarily chosen
348415 public static final Version NEEDS_UPGRADE_VERSION = Version .V_7_0_0 ;
349416
@@ -354,7 +421,7 @@ public void createSystemIndexForDescriptor(SystemIndexDescriptor descriptor) thr
354421 static final SystemIndexDescriptor INTERNAL_MANAGED = SystemIndexDescriptor .builder ()
355422 .setIndexPattern (".int-man-*" )
356423 .setAliasName (".internal-managed-alias" )
357- .setPrimaryIndex (".int-man-old" )
424+ .setPrimaryIndex (INTERNAL_MANAGED_INDEX_NAME )
358425 .setType (SystemIndexDescriptor .Type .INTERNAL_MANAGED )
359426 .setSettings (createSimpleSettings (NEEDS_UPGRADE_VERSION , INTERNAL_MANAGED_FLAG_VALUE ))
360427 .setMappings (createSimpleMapping (true , true ))
0 commit comments