Problem/Motivation
Right now, recipes have no way to tell in advance if they will apply successfully. They just sally forth and throw an exception if something goes wrong. That's limiting, and potentially frustrating, and the resulting exceptions can be pretty opaque and unclear on what went wrong.
Proposed resolution
Recipes need some way to define preconditions. I propose we take advantage of core's condition plugin API for this, and add a section to recipe.yml called preconditions, which is an associative array where the keys are condition plugin IDs, and the values are indexed arrays, where each item of the array is a set of configuration for that plugin. All conditions must check out in order for the recipe to be applied.
For example:
preconditions:
matchingEntityExists:
- entity_type_id: field_config
criteria:
# Properties to pass to an entity query.
type: image
entity_type_id: node
bundle: blog_post
- entity_type_id: node_type
criteria:
name: Blog
Translated to English, this means the recipe requires two things:
- An image field on blog_post nodes.
- A node type whose human-readable name is "Blog".
Conditions have human-readable summaries, so this would open the door to much clearer error messages about why a recipe cannot be applied.
Issue fork drupal-3461946
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
phenaproximaComment #3
phenaproximaComment #4
phenaproximaComment #5
quietone commentedComment #6
prashant.cYes, some dry-run before actually applying a recipe and show whether it can be applied or not and why it can't be applied.
Comment #7
phenaproximaA little update here.
A while ago, I spoke to @alexpott about this. He told me what his vision of this is, and if I understood him correctly, it's basically the opposite of preconditions. In other words: let's have a set of conditions that, if they are all true, mean the recipe has, in effect, already been applied. To put it another way: if all of the conditions check out, then your site is already in the same state that the recipe would have put it into.
We could glean this information already, using the information available to us in recipe.yml. If:
installlist is already installed; andconfig.importexists in the active config storage, and looks identical to what the recipe would have installed; andconfig.actionshas been done (config action plugins would probably need a new method, or a specialized add-on interface, to determine this programmatically)......then the recipe doesn't need to be applied. Everything it was going to do, has been done already.
For the sake of discussion, let's call these the recipe's "fulfillment conditions".
Now, let's take it further and suppose that a recipe could, if it wanted to, define an explicit set of fulfillment conditions, instead of relying on the system to try and figure it out. Maybe we'd have some kind of syntax in recipe.yml which allows a recipe author to state, "these are the conditions under which this recipe should be considered fulfilled." That would allow the recipe to be more lax, or more strict, in determining whether it's been fulfilled.
You'd think, then, that if we're in the middle of applying a stack of recipes, any recipe that is not already fulfilled should presumably be applied, overwriting whatever config already exists. But that's quite dangerous, because in such a situation, even a slight deviation from the default fulfillment conditions would result in the site's config getting silently blown away. I believe this is what the maddening
\Drupal\Core\Recipe\RecipePreExistingConfigExceptionthrown in ConfigConfigurator was intended to prevent.So if we go down this road and try to implement the concept of fulfillment conditions, maybe what we should do is keep our current behavior, where even the slightest difference between the recipe's config and the active config stops the recipe from being applied...but the fact that a recipe can specify its own fulfillment conditions means that there is an out for recipe authors, who can now say something like -- to use a contrived example -- "don't worry if the anonymous user role already exists and looks different; if it exists at all, consider this recipe fulfilled".
I hope this makes sense. Curious to get thoughts on it.
Comment #8
andypostKubernetes doing the same with manifests, I can't find ATM the code but I'm sure it using very similar approach
Comment #9
moshe weitzman commentedphpunit calls this PreConditions. Drupal module requirements have install time check as well.
Comment #10
thejimbirch commentedAdding #3463641: Create a way for recipes to check their preconditions as related and possibly not needed.
From @bircher in Slack.