Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
After completing a rollback on a D6 test site was surprised to see 'access denied', along with the status messages. Turns out the rollback deleted uid 1, which makes sense since uid 1 is now migrated.
But this needs to be changed to keep uid 1. I'm guessing that the user expects uid 1 to be restored to the original pre-migration values.
Proposed resolution
The destination-side code handling updating needs to set the proper rollback action.
Remaining tasks
None.
User interface changes
N/A
API changes
rollbackAction() added to MigrateDestinationInterface. This is implemented in DestinationBase, so no effect on existing implementors.
sourceid1
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#18 | interdiff.txt | 2.81 KB | mikeryan |
#18 | rollback_should_not-2598696-18.patch | 12.07 KB | mikeryan |
#12 | rollback_should_not-2598696-12-FAIL.patch | 1.97 KB | mikeryan |
Comments
Comment #2
mikeryanUm, yeah, not good... The stuff for handling uid 1 should be setting the rollback_action to to MigrateIdMapInterface::ROLLBACK_PRESERVE.
There is no means of restoring previous values (because they're not preserved anywhere), it's the same deal as simple configuration.
Comment #3
mikeryanComment #4
mikeryanD'oh! I set the rollback flag to PRESERVE and it still got deleted, so the ability to preserve seems to be broken...
Comment #5
mikeryanWe need to fix #2599152: ROLLBACK_PRESERVE is not respected first.
Comment #6
mikeryanOK, preservation in general is committed, now to fix uid 1. The test is more challenging that expected...
Comment #7
mikeryanDefinitely something we need to fix in RC.
Comment #8
mikeryanMy challenge was installing extra stuff in setUp() that the rollback touched, actual test code is straightforward. This fail patch demonstrates the issue, now on to fixing it. Which is going to be interesting, because the right fix is broader than the uid 1 case, we want to set ROLLBACK_PRESERVE generally when we're updating something that already existed pre-migration on the destination side, but need to be sure we don't set it when we're updating something we previously migrated...
Comment #10
catchComment #11
mikeryanThe fix is *almost* very simple - I have straightforward code in the destination updateEntity() which identifies what rollback action to set. The problem, however, is what I want to set is $rollbackAction in the MigrateExecutable class, which is conveniently public, but the destination doesn't have access to that class (and I don't really want it to, my goal is *less* coupling: #2543568: Remove the md_entity destination plugin hack). Flirting with putting the rollbackAction value in the Migration class, where both the executable and the destination can access it. Or, maybe just put it in the destination class and the executable can query it from there? Hmm....
Comment #12
mikeryanHere we go. Note:
Comment #14
mikeryanActually, what was needed was for the preservation test to not be digging behind the scenes to set up the preservation scenario, but to let it happen naturally (by pre-creating an entity that would be migrated over and making sure it didn't get deleted on rollback).
Ready for manual review once the automated tests pass.
Comment #15
mikeryanComment #16
mikeryanOops, noticed the rollback action was not initialized for config entities...
Comment #17
effulgentsia CreditAttribution: effulgentsia at Acquia commentedOverall, this looks quite sensible to me.
Nice cleanup of a property that doesn't appear used anywhere in HEAD, but is it strictly related to this issue? Would it make sense to split it into a separate issue for a cleaner commit history?
Can be shortened to one line. For example: "The rollback action for the last imported item.".
Lovely!
Are we sure we want to delete this test though? Are there any valid use cases for this kind of manual setting that still warrants testing?
Why 'node'? Should it be 'user'? And if so, how are tests passing without the user entity schema installed?
The var_export() is only called if you don't pass in an assertion message. So this can be something like
$this->assertNotNull($account, 'User 1 was preserved after a migration rollback');
.Comment #18
mikeryanYes, it is strictly related - this property is being moved from the executable class (where it was never set) to the destination plugin which is the natural place to set it.
Done.
Well, this segment of code was just added in #2599152: ROLLBACK_PRESERVE is not respected and needed to take a hacky approach to setting up the preservation scenario due to the bug in the current issue, so it's natural to replace it with a direct test of this issue. But, as you suggest, the saveIdMapping() could be used directly, so let's test that too.
User schema is already installed in MigrateDrupalTestBase. This is here because deleting users invokes node_user_cancel(), which does an entityQuery() on the node table (in case they might have owned any nodes).
Done.
Comment #19
effulgentsia CreditAttribution: effulgentsia at Acquia commentedThanks for the changes and explanations. #18 looks great to me. I didn't manually test though, so not setting to RTBC. But if someone does confirm that this works as expected in manual testing, I think it can be RTBC'd.
Comment #20
phenaproximaWorked OK for me!
Comment #22
webchickThere was some concern expressed in IRC by chx that this might add some unnecessary coupling. However, I think the problem here is suitably bad enough that we should get this in now and then open a follow-up when/if a better approach is discovered.
Committed and pushed to 8.0.x. Thanks!
Comment #24
chx CreditAttribution: chx commentedThat was not what we agreed on: we agreed to immediately open a major followup because this is not the right fix. I even wanted to keep this issue open as the patch committed is an architecturally broken stopgap. https://www.drupal.org/node/2603120
Comment #25
webchickCorrect, but as noted in IRC, I have no idea what the actual problem is with this patch (and the new issue doesn't explain it, either) so didn't feel in a position to do so myself.
Comment #26
phenaproximaComment #27
chx CreditAttribution: chx commentedThe problem is encapsulation violation. That's theory. In practice, "sourceid1" is an Sql idmap detail which will immediately break when you have a non sql idmap.