Problem/Motivation
There are several implicitily required properties to destination, source and process plugins. Rather than waiting for someone to WSOD when they miss one of these implicit requirements, we should throw an exception.
The MigrateSource annotation defines a source_module property which needs to identify the system which contains the source data. In Migrate Drupal's case, this property is used to identify the D6 or D7 module whose data is read by the plugin.
When providing a strong API, it's important to tell consumers when they are doing something wrong. For Migrate Drupal's purposes (our main use case), this property is required in order to inform users whether their D6/D7 data will be migrated into Drupal 8. Therefore, this blocks the completion of the core migration path to Drupal 8, and is Migrate-critical.
Proposed resolution
Throw a BadPluginDefinitionException for any source plugin that is missing the source_module property.
Remaining tasks
Write a patch, with a test, and commit.
User interface changes
None.
API changes
The source_module property will be required on all Migrate source plugins. So this constitutes a BC break.
However, we determined that for non Migrate Drupal use cases, not marking the source_module as required makes more sense. So we added an overridden migrate plugin manager that checks based on certain fairly standard migration_tags and only require source_module on migrations that use one of the tags. The tags are configurable and default to 'Drupal 6', 'Drupal 7'.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #93 | interdiff_92-93.txt | 3.28 KB | heddn |
| #93 | 2908282-93.patch | 27.43 KB | heddn |
Comments
Comment #2
heddnSource/destination are the only questionable requirements. I'd like to make them required so contrib will provide them and they will play nicely with drush or migrate_drupal_ui that needs them. We started to something like this in #2859304: Show field type migrations correctly in Migrate Drupal UI, but I'm wondering if we *do* want to break BC here.
If that's the case, then all of these should change into an exception, instead of trigger_error.
MigrateDestination
required:
not required:
MigrateProcessPlugin
required:
not required:
MigrateSource
required:
not required:
Comment #3
phenaproximaI am in favor of this, because I like active, explicit error detection. APIs like this should not be tolerant of bad input, especially if it's liable to cause weird, hard-to-debug errors and wackiness further (much further) down the line. Garbage in, exception out: that's my motto. I would much rather bail out with an error (plus clear documentation on how to correct it) than dance around bad input and deal with the support requests and bugs that then arise.
So, although this is a BC break, +1 from me.
Comment #4
maxocub commented+1 for me too.
Comment #5
heddnSo, we all seem to agree that this is a BC break and should happen. So, that means it is migrate critical and a bc break. Let's get this going then. BTW, #2859304: Show field type migrations correctly in Migrate Drupal UI covers the field plugin. This catches the rest of them.
Comment #6
heddnComment #7
heddnI think we already have the change records, we just need to make sure they are updated to note that these are hard required values.
Comment #8
heddnComment #10
heddnFixing some missing source_module source plugins. I'm sure there are more. Tagging novice to have someone run through and add the source module to more things.
Comment #12
heddnThis should make things easier to find the offending plugins, by printing the class name. And I've gone ahead and fixed several. There's bound to be more.
Comment #14
jofitzFixing some more missing source_module and destination_module plugins.
Comment #16
jofitzFix one more missing source_module source plugins.
I suspect we should not set a source_module of "migrate_drupal" because that is not enabled on the source site, but I'm not sure what it should be instead.
Comment #18
heddnInstead of migrate_drupal on the source side, we could probably use system.
Comment #19
xjmPer discussion with @catch, we're promoting the "Migrate critical" issues to critical given the importance of a stable migration path at this point in the release cycle. (The framework and release managers will confirm this in a later triage for individual issues.)
We discussed whether we were concerned about the BC break here, since this could potentially disrupt contrib. However, since the migrations would already fail eventually, this issue will just make them fail earlier and explicitly. So we'll just need to add a change record update and make the change only in the minor branch. So, moving the issue to 8.5.x.
Comment #20
xjm@heddn and @phenaproxima say there's a CR for this already somewhere but we need to edit it and add this issue to the references on it.
Comment #21
xjmhttps://www.drupal.org/node/2831566 is the CR for the previous change, so I added the reference to it and we should update it for this issue. However, we should also create a new change record draft for throwing the exceptions since it is its own BC break.
Comment #22
jofitzChanged all 6 instances of
source_module = "migrate_drupal"tosource_module = "system".Comment #24
heddnThis should hopefully fix up the remaining tests and adds some test coverage.
Comment #25
phenaproximaI like this patch a lot -- explicit error checking is absolutely better DX, so this is a welcome improvement. I do have some questions, though.
Can we remove the foreach? I understand why it's there, but it's extraneous right now since we're only checking for one property.
Additionally, I feel like it would be preferable if we gave the plugin ID here, rather than the plugin class. The ID is the canonical way to refer to a plugin.
Same here.
And here.
Forgive me for getting paranoid edge-casey, but if there was a module named "null"...unlikely as that is...could this not have bizarre side effects? How about using a non-falsy, never-could-be-a-module-name value here, like -1?
Doesn't the call to enableAllModules() also enable migration_provider_test?
I don't quite understand why this was removed? It doesn't seem to have anything to do with the problem at hand.
I'm not sure about this. Is it possible to test without enabling *all* modules? If not, we should at least explain why we need to do this.
Nit: For readability, let's just call assertSession() once and reuse the object it returns.
Comment #26
phenaproximaComment #27
maxocub commentedAdding a tag so we can see this issue in the kanban.
Comment #28
jofitzforeachand replaced$definition['class']with$definition['id'].foreachand replaced$definition['class']with$definition['id'].foreachand replaced$definition['class']with$definition['id'].Comment #29
heddnThis is actually required by the plugin system, I found out while working on tests. ID can go away. It is unreachable code.
This we want/need to stay at null. At least here.
Comment #30
phenaproximaGood, except two (optional) nitpicks:
Can these be
$this->assertInternalType('string', $source_module)?Okay, but that should be true null (
destination_module = null), not string "null" (destination_module = "null")Comment #31
heddnGoing to work on my nits.
Comment #32
heddnAdded the tests from #30 and picked up the nits from #29.
Since the null destination is actually necessary to be a valid destination, and it cannot be a migrate namespace module (we have tests making sure it isn't). And we are in-fact, mapping the data to a null destination. Therefore, semantically speaking, '/dev/null' is more clear that the data will not get imported.
Comment #33
guilopes commentedthe #32 It looks good for me
Comment #34
heddnWhat about #32 looks good. Be specific.
Comment #35
guilopes commented@heddn sorry, I mean that this address all the issues reported before ;)
Comment #36
guilopes commentedI also agree that "/dev/null" is better than just "null" or -1
Comment #37
phenaproximaMy only nit -- and it is a nit, doesn't change RTBC -- is that I was thinking we'd replace the assertTrue() with the assertInternalType().
Comment #38
phenaproximaUgh, sorry, @maxocub just reminded me -- I have to rescind RTBC because we still need change record stuff to happen.
Comment #39
phenaproximaI also have to kick this back again because this change affects the logic in DestinationBase::getDestinationModule():
As of this change, $this->pluginDefinition['destination_module'] will never be empty, so the last two logic branches are effectively unreachable.
Comment #40
heddnAdded a CR. We'll have to update the existing CR to cross-reference once this lands.
For destination... perhaps then it isn't really required? I'm going to try that.
Comment #41
heddnI've updated the new CR to only reflect source_module being required. And updated tests and implementation accordingly.
Comment #42
quietone commentedPlease explain why destination_module are label are not required. The UI form needs source_module, destination_module and label.
Sorry, this won't work. Not all variable table variables are supplied by the 'system' module. The ui won't know it is missing data.
Ditto.
The source module for i18n_variable plugin is not the system module. The sources are various submodules of i18n, but some of those issues are not yet committed.
Two things here. Most important is that this is only looking for the source_module on the definition. The source_module can also be declared in the migration yml as well. Checking by source plugin alone is insufficient. See the implementation of SourcePluginBase::getSourceModule.
And second, at first I thought this was about a process plugin because of the name, processDefinition. Don't know if it makes sense to change it, just noting my temporary confusion.
Also, destination_module can be declared in the multiple places, DestinationBase.php::getDestinationModule and Config::getDestinationModule.
edit: s/variables/variable table variables/
Comment #43
heddnGood points in #42. This was too narrow of a focus. This definitely needs more work.
Comment #44
heddnAssigning to myself to investigate more this week.
Comment #45
heddnDiscussed in the migrate maintainers meeting.
So, the preferred location for data is yaml entry (for variables, etc), followed by annotation. We do not recommend using a code based solution on the getters.
I don't know if that means we have to wait until after plugin discovery to test this, but we need to find the place where it is still in discovery mode so we can throw the exception as early as possible. We want to be able to have the exception thrown when you createInstance, etc in a kernel test.
Comment #46
heddnI'm hoping to set aside some time this next week to review this again.
Comment #47
phenaproximaI am postponing this on #2859304: Show field type migrations correctly in Migrate Drupal UI, because that issue introduces a new Migrate-specific exception that can be thrown when a plugin does not define a required property. Perfect for this issue.
Comment #48
gábor hojtsy#2859304: Show field type migrations correctly in Migrate Drupal UI landed.
Comment #49
jofitzPatch in #41 no longer applies. Re-rolled.
Comment #50
jofitzComment #53
phenaproximaHopefully this will pass the tests.
Honestly, though, I'm hugely confused by the scope of this issue. The IS is very vague regarding what plugin definition properties we consider sacrosanct, and the tests in the patch are inconsistent about it too. What exactly do we want to do here? We need to discuss this, then fix the IS, and implement a patch that fulfills all of the requirements we decide upon.
I'm also re-categorizing this issue. This is not a bug, it's an API addition to improve DX. I don't think that exactly counts as a "feature request", but that's the closest thing I can come up with. Chances are that, due to the BC break this introduces, it won't land in 8.4.x anyway.
Comment #54
phenaproximaDiscussed on IRC with @heddn and @maxocub.
We agreed that this patch and issue are too fuzzy. We will re-scope this issue, and refactor the patch, to only deal with the source_module property of source plugins.
We will also open a follow-up issue to do something similar, where applicable, to the destination_module property of destination plugins. So now that we have a clear path forward, let us:
Comment #55
phenaproximaFixed the IS.
Comment #56
phenaproximaMinor IS fixes.
Comment #57
phenaproximaOkay, I ripped out all the destination_module stuff from the patch. Now we just have to open a follow-up to reconstitute all of that code in another patch, and I think this can proceed to actual review...
No interdiff because this shed so much code that it might as well be a totally new patch.
I spent forty minutes frying my brain in front of "Santa Claus Conquers the Martians" (MST3K version, of course) while waiting for this patch to pass all of the Migrate tests locally. So I'm pretty sure this is going to pass tests.
Comment #58
phenaproximaI think the new issue scope is clear.
Comment #59
heddnLooks good to me. I reviewed the code and the assignment to (mainly) system as the source. All the values all make sense. LGTM.
Comment #60
phenaproximaThanks for reviewing, @heddn! Putting this back to NR so I remember to open the follow-up, then will return it to RTBC.
Comment #61
phenaproximaFollow-up opened: #2923810: Throw exception for destination plugins without a destination_module property. So back to RTBC as per #59.
Comment #62
phenaproximaDang it: back to NR for change record updates.
Comment #63
phenaproximaUpdated this change record, so this is back to RTBC as per #59.
Comment #64
mikeryan(still keeping one eye open on issues)
source_module is only relevant to migrations from a Drupal database, is it not? But this forces ALL source plugins (CSV, XML, etc.) to provide it, even when meaningless (I see dummy "migrate" values provided for Empty and EmbeddedData)?
This also applies (less strongly) to destination plugins (there's no reason you couldn't, now, write a destination plugin that writes to an external API).
Comment #65
phenaproximaThis is why, in retrospect, I am sad that source_module and destination_module were added to the MigrateSource and MigrateDestination annotations. They're only relevant to Migrate Drupal, but they're in all source/destination plugins. It sucks.
One possible way to make this cleaner is for Migrate Drupal to override the source and destination plugin managers, to impose the source_module and destination_module plugin definitions. That way we can prevent MIgrate from being further poisoned by Migrate Drupal's idiosyncrasies. But that said, we don't have a lot of time to bikeshed on this -- we still have entirely too many release-blocking criticals open to get caught up for long on any particular one.
Comment #66
catchMoving this back to CNR to discuss that a bit more.
I also get a bit confused by the exception handling with these, at least when running migrations via drush. The modules providing the source migrations may well be enabled on sites that don't need to migrate content from these sources (but might need to migrate content from sources they do have), however this always shows up as an error if you just do a drush mi.
Comment #67
phenaproximaDiscussed briefly with @heddn on IRC, and we decided that the best idea here might be to have Migrate Drupal override the plugin.manager.migration service with a version that enforces the source_module property, since Migrate Drupal is really the only thing that flat-out requires it. This keeps the wonkiness cleanly confined to Migrate Drupal and does not further pollute the Migrate API with Migrate Drupal-specific stuff.
Back to NW for implementation.
Comment #68
phenaproximaHere's an implementation of the idea in #67.
Comment #69
dipakmdhrm commented@phenaproxima In patch #68, the check for
source_moduleproperty is done inMigrateSourcePluginManagerofmigratemodule and not by some override inmigrate_drupal:Wouldn't that still apply for all source plugins instead of just the drupal ones?
Am I missing something in my assumption?
Comment #70
heddnre #69: I had the same thought over the weekend. I chatted briefly with @phenaproxima in IRC this morning and one idea he suggested was to look for the 'Drupal 6' or 'Drupal 7' migration tags. That's a pretty safe bet, and we are really trying to help folks here when they are missing required data. So it doesn't need to be 100% foolproof. Just catch the majority of users and tell them when they are missing required data. And I think checking the tags is a pretty good method.
Comment #71
phenaproximaLet's also ensure that the migration tags to which the source_module check should apply are configurable -- I'll add some simple config to Migrate Drupal for this purpose.
Comment #72
masipila commented+1 for the 'Drupal 6' or 'Drupal 7' migration tag approach!
Comment #73
quietone commentedMe too! Let's use the tags to identify a drupal source and then check the source_module.
Comment #74
phenaproximaOkay, here we go. An implementation of everything we've discussed since #68.
Comment #75
heddnNothing but nits:
$enforcedSourceModuleTags?
Bikeshed: getEnforcedSourceTags is better or just different?
Comment #76
jofitzI agree with both of @heddn's nits. Both changes made.
Comment #77
heddnRTBC then?
Comment #78
xjmI thought I posted on this issue already but my comment is mysteriously missing... the framework and release managers discussed this issue awhile back and agreed that it can be major, not critical, since we can add new exceptions in minor releases. So downgrading to major, but also changing it to a task since a robust API isn't just a feature. Hopefully it doesn't matter in any case since this one is RTBC again. :)
Thanks everyone!
Comment #79
phenaproximaOops! This should all be gone. Will fix in a bit.
Comment #80
phenaproximaHere we go.
Comment #81
heddnAnd back to RTBC.
Comment #82
larowlanAre these still needed now - because they're not tagged as Drupal 6/Drupal 7 and outside migrate_drupal - shouldn't be needed anymore right?
Can we get a comment here indicating why we're doing this overriding (to enforce the source module property etc)
Do we need the word 'loud' here?
Comment #83
phenaproximaAll fixed except for removing source_module from EmbeddedDataSource. That one is used in a D6/7 migration, and therefore must carry the annotation property.
Comment #84
quietone commentedI think the changes here have mean that the test migration, migration_provider_test.yml, is no longer needed.
Comment #85
phenaproximaGood point. I have removed that migration.
Comment #86
quietone commentedPatch no longer applies, so I rerolled it and fixed a typo. The changes were in MigrateUpgradeTestBase and MigrationPluginManager (the typo).
It is disconcerting for me to get a message that says 'should' when it is really a 'must'.
Since enforce_source_module is a setting in config, does that mean that it can be changed so that the enforcing doesn't take place?
The IS needs an update to include the decision to create a new Migrate Drupal MigrationPluginManager. And what does that mean for developers?
Comment #88
quietone commentedTry again, assertions were out of order.
Comment #90
quietone commentedThe failing test is unrelated, but this adds a file doc block to migrate_drupal.install.
Comment #91
heddnUpdated IS.
To clarify for the question #86 about should vs must. I think this is a grammar issue. I consider 'should' to be equal to 'must'. However, I guess in theory if you were knowledgeable and wanted to, you could disable exception throwing by altering the config so it didn't flag exceptions on Drupal sourced data. Why you would want to, I'm not sure.
Let's use the word, "tag" in the name of the config setting.
Should this move to 8.5?
Comment #92
heddnHere's fixes for my nits.
Comment #93
heddnAnd a fix from #86. for the feedback about must vs. should
Our pattern here is commerce, which also uses the language 'must'.
The checkout pane %s must define the %s property.Comment #94
heddnComment #95
heddnComment #96
maxocub commentedI like the new approach with the dedicated migration plugin manager. I don't see anything wrong in the code, the IS & CR are up to date, so RTBC.
Comment #97
larowlanAdding review credits
@xjm for CR updates, @dipakmdhrm, @mikeryan and myself for reviews that changed the patch
Comment #98
larowlanCommitted as f22b038 and pushed to 8.5.x
Published change record
Comment #100
larowlanFor posterity, the BC implications here were discussed in #19