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/install and config/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.

Remaining tasks

User interface changes

API changes

Data model changes

Comments

nedjo created an issue. See original summary.

alexpott’s picture

I'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.

nedjo’s picture

Version: » 10.0.x-dev

Another detail is default_config_hash, currently set in ConfigInstaller::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?

alexpott’s picture

Whilst 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.

wim leers’s picture

Subscribing … 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 ….

thejimbirch’s picture

Version: 10.0.x-dev » 11.x-dev
bsnodgrass’s picture

Project: Recipes Initiative » Drupal core
Component: Code » recipe system
Issue tags: +Recipes initiative

moved to Drupal Core

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.