Problem/Motivation
I have added default UUIDs to the shipping config. This is fundamentally wrong: the first U stands for Universal and we are giving the same UUIDs to many, many different objects all over the world. I felt troubled over this and asked and got confirmation in http://programmers.stackexchange.com/questions/214246/how-unique-should-... .
Proposed resolution
We already override everything except changing UUIDs is disallowed. But, we could detect whether the config has not been edited since install and if so, allow for overriding everything inlcluding UUIDs.
Remaining tasks
Either add an InstallSnapshotStorage or something -- this would store the 'install' state of the config -- and when overriding a just-been-installed something then override here as well.
Or we could do tricks with the snapshot storage to indicate that something just got imported.
Also, the new checkForConflicts method does not yet have doxygen or tests.
User interface changes
None.
API changes
None.
Related Issues
#1969800: Add UUIDs to default configuration
#2100043: Dynamically generated default YML use randomized UUIDs.
#1609418: Configuration objects are not unique
| Comment | File | Size | Author |
|---|---|---|---|
| #64 | interdiff.txt | 1.68 KB | swentel |
| #64 | 2110615-64.patch | 65.2 KB | swentel |
| #59 | interdiff.txt | 652 bytes | swentel |
| #59 | config-2110615-59.patch | 65.11 KB | swentel |
| #58 | 2110615-58.txt | 1.4 KB | swentel |
Comments
Comment #1
chx commentedDespite patch size, this is a very small change: it rolls back a 34.21kbyte patch and more, I ran
sed -i '/^uuid:/d' core/modules/**/config/*ymlComment #1.0
chx commentedUpdated issue summary.
Comment #2
tstoecklerSo my question after reading the issue summary was: "What happens if for a single config object both the local one has changed and there is one to be imported?" (i.e. the actual 3-way merge). This is what happens. Makes sense. Contrib can go crazy if it wants.
Comment #4
dawehnerHere is a test which at least works when there is a conflict.
Comment #5
Anonymous (not verified) commentedso, if i edit something on prod, i can't rely on import working. interesting new workflow restriction. certainly would simplify what we have to implement. not sure if i agree with that that new restricted workflow, but i'll think on it.
regardless of implementation, we need to put that restriction upfront with this patch, and get heyrocker/webchick etc to buy in.
Comment #7
chx commentedRe #5, currently the workflow for changed non-config entities is this:
We already unconditionally override every edit on production. I won't copy the code for config entities especially because the config entity (and its storage) could choose to pick things from
$entity->original. Let me assure you: this doesn't happen. So the new exception is just shining light on an existing, very poorly handled problem.Comment #8
Anonymous (not verified) commentedi have absolutely no idea how to respond to #7 in a useful way, so i probably shouldn't be writing this comment.
import takes the staged config, and, well, imports it. unconditionally, even, because the idea is that the target config is made to look like the staged config.
i could have sworn that was the idea, but i guess i've had it wrong all this time. unfollow.
Comment #9
chx commentedWell, actually having a fast forward is just one way to implement part of a 3-way merge --
accept --theirsis certainly another. If that's what we want, then that's what we want. Certainly easier for me.Comment #10
chx commentedOK I filed #2111199: Decide what to do on import on diverge and will continue there; in this issue I will just do enforced overrides.
Comment #10.0
chx commentedUpdated issue summary.
Comment #11
chx commentedComment #11.0
chx commentedUpdated issue summary.
Comment #12
chx commentedTo clarify: the original idea was to allow uuid change on no edit since last import (and on edit since last snapshot, throw an exception). The new idea is to allow uuid change on no edit since first snapshot and no new exception. While there's a huge behavior change and an expectation change, there's very little change necessary in the patch posted and little in the challenges ahead: we need to make snapshots differ from each other, somehow.
Comment #13
yched commentedI don't understand what this issue is about. We do want the config items that come from default config (either the install profile config or modules config) to have the same UUID on dev and prod.
So yeah, "the frontpage view shipped in standard profile", "the filtered_html input format", "the node body field" will have the same UUID across all drupal sites - I don't see where this is an actual issue ? (+ I don't really welcome the idea of completely redefining what the "import" concept means as a side effect ?)
Comment #14
chx commentedYou can't give the same UUID to different objects and they will be different when they will be edited. That violates the universality of the UUID :/
Comment #15
mtiftAs I understand it, we are using UUIDs to track changes to configuration, and that default configuration makes this process easier.
In #1969800: Add UUIDs to default configuration we solved an obvious problem for the following situation: 2 sites are installed, nothing changes, config is exported from one, imported in the other, and 50 or more changes are reported.
@chx Could you describe the problem that this issue would fix? In other words, is there some sort of test case for this problem, or is it that we are going to cause problems later because our current architecture is flawed?
Comment #16
chx commentedThe moment you try move configuration between sites having UUID in them will cause problems -- not to mention being theoretically wrong. We are using UUIDs for the wrong purpose, IMO :/
Comment #17
xjmArrrgggh. Convince me this doesn't roll deployments back to being insane. "Cause problems" and "theoretically wrong" are not helpful.
Comment #18
chx commentedI hope this convinces you.
Comment #19
xjmComment #20
chx commentedNo, the agreement on IRC is that we don't do this. I disagree but we have overwhelming majority voting against this.
Comment #21
amateescu commentedWhere was the agreement? I barely opened a conversation when you left.
Comment #22
chx commentedHere:
[Monday, October 14, 2013] [08:27:28] <msonnabaum> a uuid seems totally fine thereComment #23
msonnabaum commentedI'd prefer discussion continued.
Comment #24
chx commentedIf you want a discussion then leave yourself out of it because as long as you are there, no discussion can happen as you are given (I just don't know by whom or how) powers to even overrule core committers so there's no point in having any discussion at all.
Comment #25
Anonymous (not verified) commentedwe need a way, during an import, to differentiate between update vs delete-then-create, and rename vs delete-then-create.
a machine name is not enough information for this. we're not using a log-shipping method to track changes, so we need something. until now UUIDs are that something.
i don't care about UUIDs. i'd be ok with a patch that changed all references to UUIDs to 'originHash' or some other colour appropriate for a bikeshed. but we can't get rid of UUIDs unless we replace them with something that provides the functionality we need.
Comment #26
chx commentedI am trying to figure out a scenario where #25 is a problem.
You have a dev site a and a prod site. You have some fields installed by default. You go on with life, have content on both sites but didnt edit that specific field. You delete the field on dev where the data for that field gets nuked, recreate, import to prod, under the current rules this would be disallowed but under the new rules it would override and the data nuking wouldn't happen. Am I right that this is the problem?
Comment #27
tstoecklerI think #1969800: Add UUIDs to default configuration was not the correct solution for the deployment problem. At the very least it's not the only solution. We can find solutions for the problem there in any case so I don't really understand the anger in this issue, quite frankly.
Let's say you install two different sites - dev and prod - and at some point want to deploy the body field on articles from dev to prod. Currently, because they have the same shipped UUID, that's not a problem, you can do it. As #26 correctly notes, though, as soon you delete and re-create the field you can't. So in that case the current solution does not help at all.
So omitting the shipped UUIDs gets you in no worse of a situation than above, you have the same "conceptual" objects with a different UUID.
This problem can be solved manually by simply deleting the body field on prod. Then the one from dev can be imported without problems. So to make that problem easier we can simply do that automatically on config import. If the UUIDs differ then drop the currently active one and import the other one. So that's one of the use-cases that should be considered in #2111199: Decide what to do on import on diverge.
Again, I don't really understand why removing the default UUIDs is such a problem. We need to do some work to make config import usable for all cases in any case.
Comment #28
gddNo what should happen is that on prod the previous field would be deleted, and a new one would be recreated in its place. Exactly what happened on dev should happen on prod. That is why we need UUIDs in default config. The new field will have a different UUID, so we know it is a delete and recreate as opposed to a rename (where the UUID would remain the same.) I don't see any reason why either of the scenarios you outline would occur, neither of them makes sense. I am honestly super-confused about this whole issue.
Comment #29
yched commentedYes, being able to differenciate between updates and "delete + create different one with same name" is a critical feature of the config impor process, and this is why config entities have UUIDs. This has been a key design pattern for CMI since BADcamp 2011.
As @beejeebus wrote in #25, if this is not backed by uuids this needs to be backed by some other "random non clashing auto-generated hash", but honestly I have no idea why uuids wouldn't do the job.
Comment #30
yched commentedAlso, I don't understand #27. If you delete and recreate the field on dev, it will be deleted and recreated on prod on import, based on UUIDS being different, and that's exactly what we want.
Do we really want to re-hash all this ? :-(
Comment #31
discipolo commentedI am currently playing around with configuration import and wanted to join in with a question regarding this issues premise, not to re-hash everything but just to clarify this issues` status since it seems confusing to many.
when i read through the answer on stackexchange it seems like we are in the second situation since we want
so are we really misusing uuid fundamentally or not?
if i change the contenttypes and views that come shipped and import those on production they are still the ones that were shipped opposed to if i deleted and recreated them.
@chx could you elaborate?
Comment #32
tstoecklerRe #28 and #30: I totally agree with everything you said. No, let's not re-hash that, noone is arguing that I think. It's just that currently we support the following use-case, due to the shipped UUIDs:
You install two different sites, one dev, one prod. You then change the default 'node.body' field instances on articles and then want to deploy those changes. Because the prod site has the same UUID it will not delete-recreate but simply update.
Without shipped UUIDs this would not be supported so the question is whether we need to support this use-case. I would say no.
It is worth noting that there is only a practical difference between update and delete-recreate if you already have content in those fields. If you have a completely clean site with no content, it makes no practical difference. (This also applies to most other configuration not only field instances.)
So if you do the following: Install two sites, one dev one prod. And before you do *anything* on prod, you just do a full import from dev. That will get you into the same situation that we currently have, where all your UUIds will match on dev and prod. Therefore I don't think default UUIDs are worthwhile to keep.
Edit: Removed some stray characters.
Comment #33
xanoThis patch deletes exactly that which links field instances to fields.
Comment #34
yched commentedre @tstoeckler:
#1969800: Add UUIDs to default configuration was done after the conclusion was "we do need to support this use case - create two fresh installs, one on dev, one on prod, make config changes on dev, deploy on prod".
Not true, there is a practical difference between an update and "delete/create new" even if the field has no data - e.g you can delete and create a different field with same name & a different field type - this is forbidden in the case of an update.
More generally, let's not focus on fields. As been stated many times already in the CMI effort over the the last two years, this is about making a sane & predictable deploy flow for any config entity that triggers different code in its update() and delete() / create() flows - whether in the storage controller, in the entity type class, or in any random hook_entity_OP(). It so happens that in current core, fields are what most spectacularly breaks, but that's not relevant. So let's not reason on "but wait, in the case of fields, this and that work in this and that case if we do this or that", coz contrib will have other cases we don't want to have to predict.
CMI needs to be able to identify whether a file deploy means an update or a delete / create, plain and simple, and independently of the specifics of any specific config entity type. UUIDs in config entities files is how CMI does it.
Comment #35
webchickWhat might help this conversation move is a test case that lays out the behaviour we're trying to preserve and why, probably using fields as the test case (although I see your point about this not being specific to fields at all). Heck, even a pseudocoded test case would be great. I definitely hear the frustration of the CMI folks who feel like this has been discussed over and over again, but I also hear the confusion of people who think the two Us in UUID ought to mean what they say on the tin. :)
Comment #35.0
webchickUpdated issue summary.
Comment #35.1
mtiftAdd a related issue
Comment #36
tstoecklerI don't think the fact that we install two separate sites and then retroactively say: "Hey, you're actually just a copy of this other site!" makes much sense, TBH. Still, I think we can get the best of both worlds. We just need to provide an explicit facility to say "Wipe all config of the current site and import from a different one."
Even better: #1613424: [META] Allow a site to be installed from existing configuration would totally fix this in a sane way.
Comment #37
yched commentedSo, right, this is ultimately about "how do you setup two (or more) sites between which you intend to deploy config". As explained above, config deploy can only be expected to work between sites where the "same config entities" have the same UUIDs.
Either:
a) We intend to have "make two separate fresh installs (presumably, using the same install profile), and expect deploying from one to the other just works". In order to do this, config entities created during install need to have the same UUIDs so that they are recognized as "the same" during config import - hence fixed UUIDs in default configs.
b) We state that a) is not supported, and we require more restrictive setup steps: do a fresh install of site A, then setup site B with "some" (TBD) list of exact steps (copy files and db, edit some stuff in settings.php...). Then no need for fixed UUIDs in default config. This also means we do not support importing config between two arbitrary sites (or only creates, not updates)
The problem is that this specific point ("on what kind of setup do we expect config import to work ?") has AFAIK never had a dedicated issue as an important user story / feature definition in CMI, but only discussed / diluted in side issues like this one or #1969800: Add UUIDs to default configuration or #1703168: [Meta] Ensure that configuration system functionality matches expected workflows for users and devs (the continuing vagueness of "expected" being the crux of the issue IMO...). Scope changes during the cycle (initially we allowed partial imports, but we now only support full imports) have also probably muddied the water a bit about what we expect from CMI imports exactly.
My suggestion would be: let's have this discussion once and for all in a dedicated issue ?
Comment #38
gddWe had a discussion about this today at BADCAmp. Basically the conclusion is that it is very very difficult to work through all the different use cases and whether they will work or not without actually having a functioning system of any kind in front of us. So what we really need to do is get CMI to the point where even one basic test case will actually work. One test case we have been discussion for a long time is this
- Install minimal
- Import the config from default
- End up with default
If we can't make this very simple work then we're pretty much done. I think the whole discussion of do we support x workflow or y workflow is pretty dumb when *we cant even test or put any of these workflows in front of users yet*. So we all kind of agree that we just need to push on until we get *something* work that we can play with and try stuff out with. This will install
- Implementing validation in the interest of ...
- Getting module/enable disable on sync working and ...
- Implementing the defer process we discussed at Badcamp two years ago to manage dependency problems
Then we can revisit stuff like this. alexpott is going to create a meta-issue to track this and any other dependencies we have for this one use case.
There is one actual issue that came up around UUIDs in this discussion, and that is the problem of config that is dynamically generated at install-time (and thus can't have a default UUID specified.) I consider this a bug - any default config you need to install should be statically provided by your module. Any places that do this need to be fixed.
Comment #39
yched commentedYes, this is a real problem, and the more I think of this, the more I fear it's going to be a can of worms which makes profile/module install time a "special" runtime context where APIs behave in a weird way. More on this when we have a meta issue.
Comment #40
chx commented#38 we have a test for this and it is working -- although with testing not minimal but I doubt there's a big difference. Try standard. That's the broken one.
Comment #40.0
chx commentedAdd another related issue
Comment #41
sunAfter reading this issue, I think that the original problem statement and the more limited/focused issue title is correct:
Default config that is installed from scratch on a new site needs to get new, universally unique identifiers, in order to actually be universally unique.
Otherwise,
foo.bar.ymlis going to be the same thing on 500,000 different sites, whereas it is clearly not.I'm a bit confused by the earlier stated expectation of, when installing two independent sites, and copying the config from site A to site B, then a config import was supposed to simply "merge" everything from site A into site B, disregarding the fact that we're looking at two completely independent sites.
The expected effect of that operation should be that all config entities are deleted and recreated, because they may be similar, but are not the same.
It appears that the precondition in that expectation is the root cause: Instead of installing two different sites, you normally install one site, and you initialize your staging environments by cloning that site into a second (and third) instance. Just like you would have done it prior to D8.
For the special case of initializing a clone based on configuration only, but without content/data (e.g., dev → prod without dev data, or prod → dev for a new developer who doesn't need content/data), I once created #1613424: [META] Allow a site to be installed from existing configuration
The major difference in the operation proposed in #1613424 is that the site-clone is not installed from scratch based on default config (causing new UUIDs), but instead, the site-clone is installed based on a preexisting configuration staging directory (e.g., obtained via git), retaining existing UUIDs.
Therefore, I agree that each default config (entity) that is freshly installed should receive a new UUID when getting installed.
However, there appear to be concerns with that — unfortunately, they were not expressed/elaborated on in a way that allows us to get on the same page.
Can someone clarify what these concerns are and ideally also the related use-cases? Thanks!
Comment #42
yched commented@sun: highly confused area currently, spread around many issues :-/
See #2127573-36: Stop creating node, comment and custom block fields automatically and provide defaults in CMI (and the issues linked there) for the current state of the discussion & proposed approaches.
Comment #43
xjmComment #44
alexpottComment #45
alexpottBumping to critical to match parent task.
Comment #46
yched commented@alexpott: do we really want to keep this issue ?
If the plan is to go with #2133325: Create a site UUID on install and only allow config sync between sites with the same UUID, then sure we'll want to get rid of the hardcoded UUIDs in our default config files, but the gist of the discussion and patches here are about yet another mechanism to deal with UUIDs (the "allow UUID change just after install instead" part of the title), which becomes moot if I get things correctly.
Comment #47
xjmSo, there are three parts to this issue:
@alexpott expressed a preference for throwing an exception. In any case, I think this part of it belongs in a separate issue, and that separate issue is possibly a beta target rather than a beta blocker. I'll take care of filing that as well.
Comment #48
xjmStarter patch strips UUIDs out of default config.
Remaining instances of "uuid" in non-schema yaml files:
I think the stuff in
field_test_config/stagingis not default configuration, but is rather meant to emulate staged configuration. Need to take a closer look at the test to be sure.The patch also removes two different UUID lines from the default image styles. Something weird is going on there that needs a closer look.
Comment #50
yched commentedI think so too, yes.
Comment #51
swentel commentedOk, this fixes the Field API failures, they need the uuid entries there. I also left in the uuid entry in system.site. It gets a new one when installing and there should be one for the Field API staging tests because the storageComparer checks on it (which probably means that we might need to refactor those tests one day, but still, they work fine).
However, the failure in ConfigSingleImportExportTest() reveals something interesting: config entities managed by the system module are not recognized when the system module is installed: date format and menu config entities do not get a uuid. If you for instance supply a default date format in the node module, that one will get a uuid, which is what we want of course. Additionally, other default config entities which rely on an entity type provided by the module seem to work fine (contact module for instance), so clearing the entity info cache and a new discovery seem to work fine there.
I've attached a second patch with debugging in it which logs data to /tmp/installing which you can use to follow what happens at install.
- edit - the patches here are wrong, use the one in #55 - use the do-not-test for inspiration to log if you want to follow along on install.
Comment #55
swentel commentedOk, now the right patches.
Comment #56
swentel commentedComment #58
swentel commentedSo yeah, drupal_install_system() is a different beast. Attached is a quick hack which makes it work, obviously not the right way, but I'm going to bed now.
Comment #59
swentel commentedOk, this is more elegant, should be green.
Comment #60
swentel commentedNote, like xjm says in #48, the image effects are the only weird stuff left, but I'm going to bed now :)
Comment #61
xjmDiscussed with @swentel. We've three things for followups from this:
Comment #62
alexpottWe should leave these uuids alone. Image effects in an image style are keyed by UUID so that a style can implement the same effect more than once. We should open a follow up to remove the WTF of the effect being keyed by the uuid and having it as a value.
Comment #63
yched commentedNot even sure why effects in an image style have individual uuids to begin with.
Image styles were the first entities converted to cmi, even before thre were "config entities", they're almost as old as D7 code now...
Comment #64
swentel commentedTour and Editor didn't declare the public uuid property, so no uuid was created on install. Alex suggested adding it to ConfigEntityBase. Maybe #2198377: Enforce UUID key name in configuration entities can clean this up further. Also brought back the uuid's in the image styles, that needs more discussion in a follow up.
Comment #65
sunPlease note that the UUID keys for effects in an image style configuration are the result of a painfully hard fight to get right:
#1508872: Image effects duplicate on edit introduced them to fix a critical regression
And also:
#1782244: Convert image styles $style array into ImageStyle (extends ConfigEntity)
#1821854: Convert image effects into plugins
#1609418: Configuration objects are not unique
Unlike filters in a filter format configuration (in which each filter plugin can only exist once), an image style can contain multiple instances of the same effect. But yet, all effect instances still have to be properly identified (and diffed) when configuration is staged/synced.
But yeah, let's move that discussion into a separate/dedicated issue.
Comment #66
alexpottSo lets get the followup mentioned in #47 created and move on with this.
Comment #67
webchickOk, awesome. This has always bugged me since it first went in, happy to see it removed. :)
On IRC I asked about why we don't have existing test coverage that needs to be updated as a result of this change. Basically, #2108813: Add fancier config import/export test scenario is still in needs review state, and we changed our minds regarding supporting the "export config from arbitrary site A and import into arbitrary site B" a few months back, so the original use case that this code was meant to support is no longer valid. $uuid moves the ConfigEntityBase because it'll still be saved in active config, just not in default.
Committed and pushed to 8.x. Thanks!
We'll need a run-through the existing change notices https://drupal.org/list-changes/published?keywords_description=uuid&to_b... to check for references to this property. In particular, https://drupal.org/node/2153709 needs to be deleted.
Comment #68
xjmI cleaned up examples of UUIDs in default config in all the change records, and unpublished https://drupal.org/node/2153709 and marked it reverted.
Comment #69
xjmAdded followup #2201501: Throw an exception if a UUID is defined in default configuration. We still need one for the image effect... stuff...