Problem/Motivation
We have a module installed into a Drupal 8.2 site running Features 3.2.0. When updating the module's configuration to add a field to the content type the module manages, FeaturesManager::import() is unable to import the changes.
- The changes are not detected as new or updated
- The findPackage() method cannot find our module, though it does have a module.features.yml file.
- The getPackages() method returns an empty array.
When looking closer at the code flow, we cannot see where the packages are initialized. It appears that FeaturesManager::loadPackage() is the only spot in the code that initializes packages, but only works with the $any parameter set to TRUE, and even then we are not finding the module importing.
In discussion with Mike Potter, it seems that the import method is not detecting new configuration at all, only existing.
Proposed resolution
Adjust the import method so it can handle new configuration as well as existing.
Remaining tasks
Code, Test, Ship
User interface changes
None.
API changes
Possible new parameters in import method signature depending on implementation.
Data model changes
None expected.
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | features-drush_fr_read_extension-2852248-19.patch | 1.23 KB | timcosgrove |
| #11 | features_failure_to_import_new-2852248-11.patch | 15.11 KB | mpotter |
| #7 | features_failure_to_import_new-2852248-7.patch | 8.96 KB | mpotter |
| #6 | features_failure_to_import_new-2852248-6.patch | 9.01 KB | mpotter |
Comments
Comment #2
mpotter commentedSo, looks like 2 problems here.
First, the featuresManager::import() helper function has apparently NEVER worked. It assumes the packages have already been loaded by the ConfigAssigner. For example, see the drush commands for features-import.
So before calling ::import() you probably need to do:
However, even when you do this it won't work. That is because config_update::revert() will not create any new config, only update existing config.
The "Revert" code in config_update seems based on the code in core ConfigInstaller::createConfiguration(). This code *does* handle dependencies and also handles creating new config. I have created this issue: #2852626: Make ConfigInstaller::createConfiguration() public to see if we can make createConfiguration public so it can be called by config_update or by Features directly.
Comment #3
dmouseWhen I tried to import a new field using this code, the Drush update command show me the below error
Comment #4
mpotter commentedCorrect. That is because of what I mentioned in #2. The config_update module is not handling config dependency, so it tries to import the field_instance before the field_storage. Also, the code will never actually create "new" config.
Comment #5
mpotter commentedFYI, I was blind. The ::import() function *does* create new config. But correct that it does not handle the config dependencies.
Comment #6
mpotter commentedHere is a patch to try. It utilizes the core configInstaller::createConfiguration function, which is easier in Features since we already have our own override of the ConfigInstaller and can recast the function as public. Added a helper function in FeaturesManager to call it and return the results needed for both the ::import() function and for the Drush command output to maintain existing functionality.
Also fixed a typo in FeaturesManager::loadPackage that would prevent it from ever working.
This patch should fix the ::import() function without any need for calling the assignConfigPackages.
Comment #7
mpotter commentedSorry, that patch doesn't apply to the latest dev. Here is a re-roll.
Comment #8
mpotter commentedAnd yes, we've got to get these tests passing! Will work on that next.
Comment #11
mpotter commentedOk, there were still some problems with this patch. The ::import() function was only importing a single module, and loadPackage wasn't actually returning anything! Then, the test for ::import needed to be moved from Unit to Kernel to really do a full test. Also added a test for ::createConfiguration()
Here is the updated patch.
Comment #12
dmousethe patch#6 works for me, I going to mark this to RTBC
Comment #13
Grayside commentedI put this through some more testing, looking at both config updates and new configuration. Overall both cases successfully imported from code.
I ran the process as follows:
$> drush scr test.php
Where test.php contains:
The output was huge so I ended up deleting and tweaking config a second time to pipe it to a separate file.
Looking at it closer, it seems to be structured as:
I'm not sure if the full configuration object returned is valuable, but certainly the keys are.
There is a bit of an interface mismatch: the $any parameter is not in the interface method declaration, and the description of the @return parameter implies the return values are just the config IDs, rather than those being keys of larger objects.
Not sure to what extent the interface alignment is in scope here, but since this works to fix the bug I'm not going to remove the RTBC.
Comment #16
mpotter commentedThe patch in #11 has this for the Interface doc:
I think it was the previous patches that didn't have this. In any case, thanks for the testing. This looks good now, so committed it.
Comment #17
timcosgrove commentedSo, I think there's a problem with this patch (https://www.drupal.org/files/issues/features_failure_to_import_new-28522...). (edit:) Upon updating to this version,
drush fr / frano longer appear to work.If we look at features.drush.inc, starting at L648, we load the existing config into $config:
Pending confirmation, we assign the existing config to $config_to_create:
Then, we tell FeaturesManager to import the existing config:
At no time is the new config imported, as far as I can tell.
Digging further, but, thoughts? The above analysis is confirmed by the behavior I'm seeing:
1. Features reports features/config is overridden.
2. drush fr (and friends) report that the feature was reverted.
3. Features continues to report the features/config is overridden, and the new config is never imported.
Comment #18
timcosgrove commentedCarrying further, in FeaturesManager->createConfiguration(): http://cgit.drupalcode.org/features/tree/src/FeaturesManager.php?h=8.x-3...
We again load the existing config:
and then, check $existing_config against $config_to_create, which since it was also built from existing config, will always return empty:
There are no tests of the Drush command, so it isn't surprising this wouldn't have been caught.
Comment #19
timcosgrove commentedPatch attached that explicitly reads the extension config. This is possibly a naive approach, but it fixes `drush fr` for me.
Patch is against current, so 8.x-3.4, after the previous patches in this issue were already merged.
Comment #20
mpotter commentedThis should already be fixed by the RTBC patch in #2856466: Error: Cannot use object of type Drupal\features\ConfigurationItem as array. Please test that one and report there if doesn't work.
Comment #21
mpotter commentedAlso, please remember not to re-open issues and add a new patch that already have committed patches. It confused the patch process. Just create new issues so patches can be better tracked. Changing this back to Closed/Fixed from #16.