There's some cleanup to be done in `FeatureMigrationIT` and related classes.

- [x] Convert `static` `preMigrationHook` and `postMigrationHook` to use instance members, retrieved from the `internalCluster()`
- [x] Use Hamcrest matchers as described [in this comment](https://github.com/elastic/elasticsearch/pull/84192/files#r812224067) for better failure output
- [x] Rename `createSimpleSettings` to `createSettings`
- [x] Rename `createSimpleMapping` to `createMapping`
- [x] add support for unknown fields https://github.com/elastic/elasticsearch/pull/84258#pullrequestreview-890890422
modules/reindex/src/internalClusterTest/java/org/elasticsearch/migration/MultiFeatureMigrationIT.java
assertThat(migrationResponse.getReason(), nullValue());
        assertThat(migrationResponse.getElasticsearchException(), nullValue());
        final Set<String> migratingFeatures = migrationResponse.getFeatures()
            .stream()
            .map(PostFeatureUpgradeResponse.Feature::getFeatureName)
            .collect(Collectors.toSet());
        assertThat(migratingFeatures, hasItems(FEATURE_NAME, SECOND_FEATURE_NAME));
        
        assertThat(hooksCalled.await(30, TimeUnit.SECONDS), is(true));
        GetFeatureUpgradeStatusRequest getStatusRequest = new GetFeatureUpgradeStatusRequest();
        assertBusy(() -> {
            GetFeatureUpgradeStatusResponse statusResponse = client().execute(GetFeatureUpgradeStatusAction.INSTANCE, getStatusRequest)
                .get();
            logger.info(Strings.toString(statusResponse));
            assertThat(statusResponse.getUpgradeStatus(), equalTo(GetFeatureUpgradeStatusResponse.UpgradeStatus.NO_MIGRATION_NEEDED));
        });
        assertTrue("the first plugin's pre-migration hook wasn't actually called", preMigrationHookCalled.get());
        assertTrue("the first plugin's post-migration hook wasn't actually called", postMigrationHookCalled.get());
        assertTrue("the second plugin's pre-migration hook wasn't actually called", secondPluginPreMigrationHookCalled.get());
        assertTrue("the second plugin's post-migration hook wasn't actually called", secondPluginPostMigrationHookCalled.get());
        Metadata finalMetadata = client().admin().cluster().prepareState().get().getState().metadata();
        
        FeatureMigrationResults currentResults = finalMetadata.custom(FeatureMigrationResults.TYPE);
        assertThat(currentResults, notNullValue());
        assertThat(currentResults.getFeatureStatuses(), allOf(aMapWithSize(2), hasKey(FEATURE_NAME), hasKey(SECOND_FEATURE_NAME)));
        assertThat(currentResults.getFeatureStatuses().get(FEATURE_NAME).succeeded(), is(true));
        assertThat(currentResults.getFeatureStatuses().get(FEATURE_NAME).getFailedIndexName(), nullValue());
        assertThat(currentResults.getFeatureStatuses().get(FEATURE_NAME).getException(), nullValue());
        assertThat(currentResults.getFeatureStatuses().get(SECOND_FEATURE_NAME).succeeded(), is(true));
        assertThat(currentResults.getFeatureStatuses().get(SECOND_FEATURE_NAME).getFailedIndexName(), nullValue());