After applying a recipe that used config: import > module_name: '*', the following modules errored out.

search_api_solr

In RecipeConfigInstaller.php line 53:
The configuration 'search_api_solr.solr_field_type.text_ar_6_0_0' has unmet dependencies
dependencies:
  module:
    - search_api_solr
    - language
  config:
    - language.entity.ar

I did not have the language installed in my recipe.

Scheduler module also.
The configuration 'views.view.scheduler_scheduled_commerce_product' has unmet dependencies

Taxonomy module also.

The configuration 'views.view.taxonomy_term' has unmet dependencies

I didn't have the node module installed.

Temporary workaround is specifying the specific configuration needed in the config: import section.

Comments

thejimbirch created an issue. See original summary.

thejimbirch’s picture

Title: Optional configuration is imorted even when module dependencies aren't there. » Optional configuration is imported even when module dependencies aren't there.
thejimbirch’s picture

Issue summary: View changes
thejimbirch’s picture

Importing all configuration from the sitemap module also has this behavior.

The configuration 'tour.tour.sitemap' has unmet dependencies

Sitemap module has the following config:

install/sitemap.setting.yml
optional/tour.tour.sitemap.yml

This can be remedied in the recipe creation from changing:

config:
  import:
    sitemap: '*'

to

config:
  import:
    sitemap:
      - sitemap.settings

But ultimately, shouldn't recipe's config import have the same behavior as installing a module and only import config if all dependencies are met?

aangel’s picture

I'm seeing the same thing with Redirect on a Standard install:

The configuration 'language.content_settings.redirect.redirect' has unmet dependencies

From Redirect:

dependencies:
 - drupal:path_alias
 - drupal:link
 - drupal:views
phenaproxima’s picture

My knee-jerk reaction here is to think that, if your recipe has a line like this:

config:
  import:
    taxonomy: '*'

...then all of Taxonomy's config should be imported, the same way it would be if you installed it as a regular module (i.e., where optional config is only installed if the dependencies are there).

wim leers’s picture

Still wondering how this may or may not mess up the deterministic intent — I’ll need to dig in to how optional config works exactly today first though.

Looking at \Drupal\Core\Config\ConfigInstaller::installDefaultConfig(), this is the relevant section:

    // During a drupal installation optional configuration is installed at the
    // end of the installation process. Once the install profile is installed
    // optional configuration should be installed as usual.
    // @see install_install_profile()
    $profile_installed = in_array($this->drupalGetProfile(), $this->getEnabledExtensions(), TRUE);
    if (!$this->isSyncing() && (!InstallerKernel::installationAttempted() || $profile_installed)) {
      $optional_install_path = $extension_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
      if (is_dir($optional_install_path)) {
        // Install any optional config the module provides.
        $storage = new FileStorage($optional_install_path, StorageInterface::DEFAULT_COLLECTION);
        $this->installOptionalConfig($storage, '');
      }
      // Install any optional configuration entities whose dependencies can now
      // be met. This searches all the installed modules config/optional
      // directories.
      $storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_OPTIONAL_DIRECTORY, StorageInterface::DEFAULT_COLLECTION, FALSE, $this->installProfile);
      $this->installOptionalConfig($storage, [$type => $name]);
    }

AFAICT that:

  • installs ALL optional config
  • of ALL installed extensions
  • after ANY extension is installed
  • at ANY time.

I wonder if this still makes sense in a Recipes world 🤔 Because what if some contrib module that you installed eons ago gains additional optional config in some new version along the way? Then applying a Recipe would install that new optional config too, which AFAICT would be an unwanted side effect? 🤔

phenaproxima’s picture

My feeling is that optional config, as we currently understand it, starts breaking down in the context of recipes.

What I'm leaning towards here is "recipes must be absolutely explicit about everything" -- so that, in the config:import section of recipe.yml, they can specify any config from a given extension, regardless of whether it's part of the extension's optional config. If a recipe says something like taxonomy: '*', it does not import optional config.

In other words: if you want to bring in an extension's optional config, you need to explicitly ask for it by name.

wim leers’s picture

Status: Active » Needs review
Issue tags: +Needs subsystem maintainer review

I'm not sure if #8 is realistically achievable. Curious what Alex thinks.

konfuzed’s picture

Having now run into this conflict while testing a new recipe-based installation, there really seem to be 4 types of configuration imports that are targeted and we should help make it explicit what group of configuration will be brought in:

  1. none -- just activate the module, whether to avoid conflicts or because it's not needed due to nature of the module
  2. required / basic install config files -- could be handled by a keyword of 'default' or 'required' to just get the files in the config/install directory
  3. all aka "*" -- that pulls in config/install and config/optional
  4. explicit selection of files for any reason

I think common usage makes "*" much easier to read as a "yes I really mean everything in all of the module's config directories" easier on the mental processing and expected outcome.

thejimbirch’s picture

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

@konfuzed I think that's over-complicating it.

  1. NULL: Import none of the config
  2. *: import all the module's config, exactly like would happen if you installed the module through the UI. (optional if dependencies are met)
  3. Explicitly listed (see note below)

The part in #8 I don't agree with, is installing optional config if asked for by name regardless if dependencies are met or not. There is not a single use-case I can think of to install some config that is dependant on another module without installing the module itself, otherwise it wouldn't have the dependency...

See #3454444: Document the reason why recipes don’t import a module’s config entities by default

thejimbirch’s picture

Status: Needs review » Closed (works as designed)
Issue tags: -Needs subsystem maintainer review

This has been documented that recipe authors need to be declarative about what config they import. By using module_name: '*', the recipe author needs to include all of the dependencies of that config.

Closing as works as designed.