The D6 and D7 user migrations skip import of uid 1, because we don't want to overwrite the D8 admin account. If all Drupal websites followed best practices, and basically only used the uid 1 admin account for install.php/update.php, this would be fine. However, in a large proportion of real-world Drupal websites, the admin account has been used to author content. If that account had a different username that the D8 admin account, the original D8 username is displayed. If that account had profile fields, they are not applied to the D8 account.
The problem here is, the right thing to do is going to be site-specific. The current behavior will be correct (well, almost, see below) for a lot of sites. Others may want at least the username migrated, perhaps email address, quite likely any profile fields if they exist. Those who've seen the light might want to migrate the original admin account to a fresh non-admin account, to follow best practices going forward.
Even when skipping the admin account entirely is correct, we do have some problems with how that works now. Because the admin account is not recording in the user map table, attempts to use the migration process plugin for user references will fail, even though they should succeed because the D8 uid 1 does correspond to the source site's uid 1. So, minimally, in this case we should make a dummy map row (sourceid1=1, destid1=1) to fix this.
Beyond that, when we build custom Drupal-to-Drupal migration tools in contrib, we'll want to offer an array of options. What is the minimum we need to core to make it possible to do this? And, should we revisit whether skipping uid 1 is the right default for the core upgrade case?
Comment | File | Size | Author |
---|---|---|---|
#47 | 2560637-47.patch | 10.55 KB | phenaproxima |
#45 | interdiff-2560637-39-45.txt | 1.3 KB | phenaproxima |
#45 | 2560637-45.patch | 10.53 KB | phenaproxima |
#39 | interdiff-2560637-33-39.txt | 3.29 KB | phenaproxima |
#39 | 2560637-39.patch | 8.83 KB | phenaproxima |
Comments
Comment #2
webchickI learned in #2423103: Migration Files for Drupal 7 Content that we don't export uid 1 currently at all from the dump scripts, which is a pretty big deviation since literally every Drupal database has uid 1 (often with nodes/comments attributed to them).
Escalating to a Migrate critical.
Comment #3
mikeryanNote that #2 is a different aspect of uid 1 WTFness - I was speaking of the fact that the source plugin excludes uid 1 from the query (affecting real site migrations), while #2 is about the fact that it isn't even in the dumps for testing (affecting tests).
Comment #4
phenaproximaOne possibility is to add configuration to the entity:user destination detailing how to handle uid 1. Something like this:
This would instruct the destination to allow only the name and mail properties of user 1 to be overwritten by data from the migration.
Comment #5
neclimdulI'm actually going to argue a bit different. Just migrate the whole account an overwrite it unconditionally. If people are using best practices, then they're still using best practices. If they aren't, they're going to be frustrated and complain and work around it afterwards anyways.
Also, that will allow us to migrate d.o someday. We love you Dries.
Comment #6
phenaproximaBlocked by #2562695: migrate-db.sh skips uid 1 but shouldn't, which is needed in order to create tests.
I talked about this a little with the good people of IRC, and we concluded that by default we want to migrate uid 1 as it exists in the source site, so as to keep the upgrade path as non-disruptive as possible. But at the same time we want to give power users the option of controlling the properties that get overwritten. This patch adds such overwrite-protection support to all content entity destinations (in order to avoid repeating code), and removes the explicit skip over uid 1 from the source plugins.
Comment #7
phenaproximaUnblox0r3d.
Comment #10
phenaproximaComment #11
phenaproximaRe-rolled.
Comment #14
phenaproximaThis oughta pass the tests, at least...
Comment #15
benjy CreditAttribution: benjy at PreviousNext commentedThis approach makes sense, we had something similar in D7 with System of Record. NW because we definitely need some good test coverage around this.
Lets improve the comments to say, if overwrite is not set then we overwrite every field.
It might also be worth some docs somewhere that explains how'd you go about overwriting all but one field, probably a hook_entity_ENTITY_TYPE_load().
Comment #16
phenaproximaAgreed.
Comment #17
mikeryanPreumature for a full review, of course, but I like this approach.
Comment #18
phenaproximaAdded a test, but I'm not sure if it's enough. Any other test case ideas are welcome!
Comment #19
quietone CreditAttribution: quietone commentedPlease, can we make this clearer, change the variable name to reflect what it does instead of what it doesn't do? The default case is to overwrite everything, so the new key is about declaring what fields are to be preserved/saved. So why not something like 'preserve' or 'save'?
Comment #20
benjy CreditAttribution: benjy at PreviousNext commentedTests look good. I also agree with quietone, preserve seems the more logical way to approach this although I do wonder if we should be more explicit like preserve_fields ? Probably good to get some DX import from others on that one.
Comment #21
phenaproximaFlipped the logic and renamed the configuration option to preserve_properties.
Comment #22
quietone CreditAttribution: quietone commentedThat is much easier to follow now, thx.
+1 RTBC
Comment #23
chx CreditAttribution: chx commentedI would be much happier with an overwrite properties configuration which supports deep properties. Here's why:
Supporting deep with preserve has some serious challenges.
Comment #24
phenaproxima@chx: I don't follow...what is the benefit?
Comment #25
benjy CreditAttribution: benjy at PreviousNext commented+1 to supporting nested properties, that's a good idea.
Comment #26
phenaproximaI'm in favor of nested property support as well, I simply a) don't understand how chx's code snippet accomplishes this, and b) why that necessitates "overwrite" logic rather than "preserve".
Comment #27
chx CreditAttribution: chx commented@phenaproxima sorry I edited my comment: I got to this from wanting to support deep properties (as we do everywhere) and I can't readily see how to (easily) implement that for preserve.
Comment #28
phenaproximaAhhh, OK -- looking at the code of Row::setDestinationProperty(), I see why this makes sense. Yeah, I like that approach as well, and I can see why preserve logic would be much harder with nested properties.
Will alter the patch tomorrow.
Comment #29
phenaproximaOK, took a slightly different path here. By adding a method to clear destination properties (Row::clearDestinationProperty), we can support both overwrite and preserve logic. The tests pass, so...maybe this will please everyone?
Comment #30
phenaproximaEr.
Comment #31
phenaproximaD'oh! Forgot to remove Row::cloneSource(), which is an artifact from my implementation of @chx's idea in #23.
Comment #32
phenaproximaI just realized that my attempt to, um, preserve the preservation logic may not actually work, and we may only be able to support overwrite logic. Because to preserve nested destination properties, we'd need to be able to get a list of every single destination property at every level in order to avoid overwriting nested properties that are not listed in preserve_properties.
Comment #33
phenaproximaRe-did it, implementing #23.
Comment #34
quietone CreditAttribution: quietone commentedI totally agree with chx about supporting deep properties.
Happy with this the way it is.
Comment #35
quietone CreditAttribution: quietone commentedbenjy, just pointed out on IRC that this 'needs tests for the nested property aspect'.
Comment #36
benjy CreditAttribution: benjy at PreviousNext commentedI think we should add tests for the nested property aspect that we now support.
Also, I think we need to document an example of how to use this, maybe in the codebase? and then definitely here somewhere: https://www.drupal.org/node/2127611
Comment #37
chx CreditAttribution: chx commentedPlease do not use the name of a living person in the tests (or anywhere).
Comment #38
phenaproximaSo it's OK if I change it to Graham Chapman? =P
Comment #39
phenaproximaFixed! And added a test of nested property overwrites, too :)
Comment #42
phenaproximaPIFR has been shut off, so I don't think we'll be seeing any more bogus failures. :)
Comment #43
benjy CreditAttribution: benjy at PreviousNext commentedRTBC for me, maybe we should have a change record here as another way to document this functionality, and then a link to the migrate docs?
Comment #44
chx CreditAttribution: chx commentedAdd a testmodule.info.yml, a testmigration under it instead of the overrides in PHP code. It's imperative we show people how to use stuff. If core doesn't do something contrib will rarely do it (vica versa: if core does something consistently, contrib will copy it irregardless whether it's relevant or not).
Comment #45
phenaproximaLike this?
Comment #46
benjy CreditAttribution: benjy at PreviousNext commentedThe sample module and sample migration look good, I just think we should use them in the test.
Comment #47
phenaproximaHow's this?
Comment #48
benjy CreditAttribution: benjy at PreviousNext commentedLets do it!
Comment #49
webchickAwesome, really happy to see this fixed. The overwrite ability seems like it may come in handy other places too, not just here.
Committed and pushed to 8.0.x. Thanks! :D
Comment #51
webchickOops, forgot my tags. Since this is a) only touching Migrate, which is an experimental module and b) a "critical" (as in Migrate critical), it is eligible for RC.