summaryrefslogtreecommitdiff
path: root/lib/chef/provider_resolver.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/provider_resolver.rb')
-rw-r--r--lib/chef/provider_resolver.rb87
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