Problem/Motivation
Merging configuration into migration plugins at runtime is more difficult than it needs to be:
$migration = \Drupal::service('plugin.manager.migration')->createInstance('d6_file');
// Must pull out entire source configuration, modify it, and put it back.
$source = $migration->getSourceConfiguration();
$source['constants']['source_base_path'] = $source_base_path;
// set() only exists to work around this problem - see #2796755: [PP-1] Deprecate Migration::set()
$migration->set('source', $source);
when it could be
$configuration['source']['constants']['source_base_path'] = $source_base_path;
$migration = \Drupal::service('plugin.manager.migration')->createInstance('d6_file', $configuration);
Part of the problem is that createInstance() does not conform to the documented API (FactoryInterface). The $configuration passed to createInstance() is supposed to be simply the plugin's configuration, but as currently implemented the caller must wrap it in an array keyed by the plugin ID.
Proposed resolution
Properly implement createInstance(), and do a deepMerge() on the configuration.
Remaining tasks
None.
User interface changes
n/a
API changes
No change to documented APIs - MigrationPluginManager::createInstance() behavior changed to conform to API.
Data model changes
n/a
Original issue summary
Problem/Motivation
MigrateUpgradeRunBatch manually sets destination configuration onto the migration after loading it, this should not be needed.
Proposed resolution
Find a solution.
Remaining tasks
Write a patch
User interface changes
n/a
API changes
Likely we'll need a way for sources and destinations to accept their required configuration
Data model changes
n/a
| Comment | File | Size | Author |
|---|---|---|---|
| #26 | interdiff.txt | 728 bytes | mikeryan |
| #26 | migrate_sources_and-2681869-26.patch | 5.4 KB | mikeryan |
| #18 | interdiff.txt | 1.22 KB | mikeryan |
| #18 | migrate_sources_and-2681869-18.patch | 5.32 KB | mikeryan |
Comments
Comment #2
mikeryanAny work being done on this? It was suggested at https://www.drupal.org/node/2625696#comment-10955205 that this would address the issue of being able to discover only relevant migration plugins. I'm working on getting migrate_tools and migrate_plus working against 8.1.x #2667368: Make migrate_tools work with Drupal 8.1.x and it's not looking good so far...
Comment #3
mikeryanAnother big problem here (besides the run-time destination injection in the issue summary) is the source connection information. The upgrade UI stores source connection key and database info in state keyed as (e.g.) migrate_drupal_6. Previously it set the 'database_state_key' configuration on each source plugin to that key - now it instead sets a global migrate.fallback_state_key. SqlBase::getDatabase() uses this global fallback key for all migrations if there is no explicit database_state_key on the source - even non-Drupal migration, and even if the source plugin contains explicit database configuration.
Previously configuration for migrations was simply part of the configuration entity, now we need a way to save any added/overridden configuration for migration plugins and load it with the plugins. How/where do we do that?
Comment #4
benjy commentedYeah you're correct, the global key was added in the plugins patch.
How come you can't set a database_state_key in source anymore? I still see
if (isset($this->configuration['database_state_key'])) {in SqlBase::getConnection() ?Comment #5
mikeryandatabase_state_key is still supported in the general Sql plugin, so general migration can (and should!) use it, but the migrations-as-plugins patch removed the upgrade UI's use of it in favor of that global fallback_state_key.
Comment #6
mikeryanComment #7
mikeryanComment #8
benjy commentedI discussed this with chx and he suggested merging the configuration with the definition, it's a simple solution but it could just work. Initially I was thinking plugins would need a way to state required configuration and maybe even provide the relevant API's to collect that data from the runners but this approach solves the nasty and it's very inline with how plugins work.
Comment #9
benjy commentedah, left a debug in there, will remove later.
Comment #10
mikeryanLooks good! It does runtime plugin configuration injection just how plugins were designed, so... yeah.
I'll hold off on RTBC - it'd be good to get another pair of eyes in case we're missing something obvious. Also, note that whichever of this or #2695297: Refactor EntityFile and use process plugins instead gets in first, the other will need to be rerolled (since both touch where source_base_path is set on upgrades), and I'd like to see that one committed first...
Comment #11
mikeryanPostponing on #2695297: Refactor EntityFile and use process plugins instead.
Comment #12
mikeryanEntityFile refactor is in. If I'd known how long it would take that one, I wouldn't have postponed this one, but we can reroll now...
Comment #13
mikeryanReroll for 8.2.x with the EntityFile patch. If we still want to commit this to 8.1.x the patch in #8 is the one to go.
I've tested this manually - ran an upgrade through the UI with an HTTP source and the files were properly migrated, demonstrating that the configuration was properly set.
Comment #14
phenaproximaIt looks OK to me.
Comment #15
alexpottThese fixes looks testable.
It is a shame we still have to do this special casing. There is an issue about this somewhere.
Comment #16
mikeryanTest added, let me know if there are any scenarios you'd like added. The interdiff is kinda funky, MigrationPluginManager didn't actually change...
I don't see one. The idea is that only the migrations with entity:file destinations need the source_base_path - I'm not sure what else we can do here (other than just stuff source_base_path into all migrations). Anyway, I think that's out-of-scope here.
Comment #17
phenaproximaThis comment, and the other one in the data provider, are vague. I don't understand what it's talking about. Can this be better documented? Other than that, I don't yet see a problem.
Comment #18
mikeryanComment #19
phenaproximaAh! Better -- now I see what this is trying to do. Assuming the tests pass, and that nobody wants additional test scenarios, I'm comfortable with this change. RTBC.
Comment #20
andypostmakes sense
is not this a api change?
configuration passed differently... now
Comment #21
mikeryanThat's not an API change - it's fixing createInstance() to conform to the documented API (FactoryInterface). The $configuration passed to createInstance() is supposed to be simply the plugin's configuration, but without this change that would only worked if the caller had wrapped it in an array keyed by the plugin ID (which createInstance() now does for you, as it should be).
That being said, we should have a change record demonstrating how you can now merge configuration into migration plugins more cleanly...
Comment #22
mikeryanDraft change record added.
Comment #23
mikeryanNote that this fix will obviate the need for Migration::set(): #2796755: [PP-1] Deprecate Migration::set()
Comment #24
xjmAs an improvement to an experimental module, this is rc eligible per: https://www.drupal.org/core/d8-allowed-changes#rc
Comment #25
alexpottWhilst the changes on this issue are an improvement they are not really addressing the fundamental issue that the
MigrateUpgradeRunBatch::run()method has to know that it needs to set this configuration. Before proceeding with this patch we need:Comment #26
mikeryanAs requested.
Comment #27
heddnAdded link to #2804611: Migrate sources and destinations need a way to get their requirements
Comment #28
phenaproximaComment #29
alexpottCommitted and pushed 2a3217c to 8.3.x and a707147 to 8.2.x. Thanks!
Removed unused uses on commit.
Comment #33
quietone commentedPublished change records Configuration may be merged into migration plugins through createInstance()