Problem/Motivation
Applying a recipe includes various configuration-related tasks:
- For both modules and themes, call a specialized extension installer that installs any simple configuration the extension provides but does not install any configuration entities. (TBD: is optional simple configuration a thing? Does the modified installer need to determine what optional simple configuration to install?)
- Assemble specific configuration entities provided directly by the recipe and specified from extensions installed by the recipe.
- For extensions where a configuration wildcard is given, determine all installable config from
config/installandconfig/optional. Since the recipe itself can change the conditions for optional configuration, calculation of installable optional configuration needs to take into account all configuration provided or installed by the recipe. - Apply any configuration actions (alters), which may apply to either configuration that the recipe specified for installation or to configuration already available on a site.
- Install the resulting configuration, which involves both (a) creating new configuration and (b) updating existing configuration. (Deletion is intentionally left out of the spec.)
Proposed resolution
There are two potentially applicable core classes: ConfigInstaller, used for installing extension-provided config, and ConfigImporter), used mainly in staging configuration between environments. Which is the better choice here?
In some ways ConfigInstaller seems like the more obvious choice, since it's already specialized for installing from extensions. For example, it includes logic for determining what optional config is installable.
But it also lacks key functionality. Built to a more comprehensive spec, ConfigImporter has robust support for updating existing config. And for optional config handling, there's already a use case for generalizing it: ConfigInstaller: #2960888: Make config/install and config/optional methods reusable for config update use case.
Comments
Comment #2
alexpottI've been mulling this over. In order to use the config importer we'd have to provide a full set of site config. So we could use a config transformer that combines the recipes with the active config. We need need to add the config according to what is defined in the recipe and modify core.extension.
All in all I feel we'll be gaining some things like validation and code-reuse and maybe less solving the same problems. I do have concerns though, that we'll get some complexity too. There are two issues that come to mind.
Module weights
When modules are installed sometimes a weight is set using module_set_weight(). This results changing core.extension. We'd not know the module weight when adding the new modules to core.extension. So we'd need to update the source config with the weights post module install. Because if we don't the config importer will detect that core.extension does not match and it will re-import it and set the weights back to 0.
Config entity UUIDs
In order for the ConfigImporter to work with config entities they must have UUIDs - this is how it determines whether to create, update (or delete). I think this opens up a discussion I've been pondering... should config in a recipe's config folder have UUIDs. I'm torn about this and feel just as conflicted as I do about the fact that module provided config entities do not have UUIDs.
Comment #3
nedjoAnother detail is
default_config_hash, currently set inConfigInstaller::createConfiguration(). We've already got a bunch of hacks in contrib to get around the fact that's embedded in a place it can't be reused. This reminded me it's an issue everywhere we're updating extension-provided config too; opened #3293690: Default config hash not updated when configuration is updated.Related: does config provided directly by a recipe support localization via a localization server?
Comment #4
alexpottWhilst working on #3292282: Extend recipe runner to create configuration provided in the recipe's /config folder I've been keeping this issue in mind. So far I've gone with extending the ConfigInstaller because of the UUID and default config hash capability. However I think we should leave this issue open.
I've pondered about whether we could instead export all the site config and then the recipe could edit the exported config and then we could re-import it using the config importer. Sometimes I think this might be an amazing way to go - but other times I get a gut feeling that making applying recipes and config import the same thing will lead to more problems than it solves. At one point I tried very hard to make config import and module install work the same but @beejeebus convinced me (several times) that this was going down a hole that would be difficult to get back out of.
Comment #5
wim leersSubscribing … especially interested in how this touches on conf validation. See my proposal around that in #2164373-28: [META] Untie config validation from form validation — enables validatable Recipes, decoupled admin UIs ….
Comment #6
thejimbirch commentedComment #7
bsnodgrass commentedmoved to Drupal Core