diff options
Diffstat (limited to 'lib/chef/provider_resolver.rb')
-rw-r--r-- | lib/chef/provider_resolver.rb | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/chef/provider_resolver.rb b/lib/chef/provider_resolver.rb index 5e887225e4..7c7bac0443 100644 --- a/lib/chef/provider_resolver.rb +++ b/lib/chef/provider_resolver.rb @@ -20,6 +20,93 @@ require 'chef/exceptions' require 'chef/platform/provider_priority_map' class Chef + # + # Provider Resolution + # =================== + # + # When you type `service 'myservice' { action :restart }` in a recipe, a whole + # string of events happens eventually leading to convergence. The overview of + # that process is described in `Chef::DSL::Recipe`. Provider resolution is + # the process of taking a Resource object and an action, and determining the + # Provider class that should be instantiated to handle the action. + # + # The process happens in three steps: + # + # Explicit Provider on the Resource + # --------------------------------- + # If the resource has its `provider` set, that is used. + # + # Dynamic Provider Matches + # ------------------------ + # In this stage, we call `provides?` to see if the Provider supports the + # resource on this platform, and then we call `supports?` to determine if it + # can handle the action. It's a little more complicated than that, though: + # + # ### Provider.provides? + # + # First, we go through all known provider classes (all descendants of + # `Chef::Provider`), and call `provides?(node, resource)` to determine if it + # supports this action for this resource on this OS. We get a list of all + # matches. + # + # #### Defining provides + # + # The typical way of getting `provides?` is for the Provider class to call + # `provides :name`. + # + # The Provider may pass the OS, platform family, platform, and platform version + # to `provides`, and they will be matched against the values in the `node` + # object. The Provider may also pass a block, which allows for custom logic + # to decide whether it provides the resource or not. + # + # Some Providers also override `provides?` with custom logic. + # + # ### Provider.supports? + # + # Once we have the list of willing providers, we filter it by calling their + # `supports?(resource, action)` method to see if they support the specific + # action (`:create`, `:delete`) or not. + # + # If no provider supports the specific action, we fall back to the full list + # of matches from step 1. (TODO The comment says it's for why run. I'm not + # sure what that means specifically yet.) + # + # ### Priority lists: Chef.get_provider_priority_array + # + # Once we have the list of matches, we look at `Chef.get_provider_priority_array(node, resource)` + # to see if anyone has set a *priority list*. This method takes + # the the first matching priority list for this OS (which is the last list + # that was registered). + # + # If any of our matches are on the priority list, we take the first one. + # + # If there is no priority list or no matches on it, we take the first result + # alphabetically by class name. + # + # Chef::Platform Provider Map + # --------------------------- + # If we still have no matches, we try `Chef::Platform.find_provider_for_node(node, resource)`. + # This does two new things: + # + # ### System Provider Map + # + # The system provider map is a large Hash loaded during `require` time, + # which shows system-specific providers by os/platform, and platform_version. + # It keys off of `node[:platform] || node[:os]`, and `node[:platform_version] + # || node[:os_version] || node[:os_release]`. The version uses typical gem + # constraints like > and <=. + # + # The first platform+version match wins over the first platform-only match, + # which wins over the default. + # + # ### Chef::Provider::FooBar + # + # As a last resort, if there are *still* no classes, the system transforms the + # DSL name `foo_bar` into `Chef::Provider::FooBar`, and returns the class if + # it is there and descends from `Chef::Provider`. + # + # NOTE: this behavior is now deprecated. + # class ProviderResolver attr_reader :node |