diff options
author | danielsdeleo <dan@opscode.com> | 2012-12-20 08:33:33 -0800 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2012-12-27 09:37:44 -0700 |
commit | 88f3c2703c1a9faaa65e94c1f56260eda22982e4 (patch) | |
tree | 40dad61a4e7fe79b73d4bd1926f5f10944da3d24 /lib/chef/provider/lwrp_base.rb | |
parent | f132b98c4faddcaee5002105a6aa647bbb549c19 (diff) | |
download | chef-88f3c2703c1a9faaa65e94c1f56260eda22982e4.tar.gz |
[CHEF-3681] add inline compilation option for LWRP
Diffstat (limited to 'lib/chef/provider/lwrp_base.rb')
-rw-r--r-- | lib/chef/provider/lwrp_base.rb | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/chef/provider/lwrp_base.rb b/lib/chef/provider/lwrp_base.rb index 1ae17e288c..90ce70ae61 100644 --- a/lib/chef/provider/lwrp_base.rb +++ b/lib/chef/provider/lwrp_base.rb @@ -27,6 +27,48 @@ class Chef # Base class from which LWRP providers inherit. class LWRPBase < Provider + # Chef::Provider::LWRPBase::InlineResources + # Implementation of inline resource convergence for LWRP providers. See + # Provider::LWRPBase.use_inline_resources for a longer explanation. + # + # This code is restricted to a module so that it can be selectively + # applied to providers on an opt-in basis. + module InlineResources + + # Class methods for InlineResources. Overrides the `action` DSL method + # with one that enables inline resource convergence. + module ClassMethods + # Defines an action method on the provider, using + # recipe_eval_with_update_check to execute the given block. + def action(name, &block) + define_method("action_#{name}") do + recipe_eval_with_update_check(&block) + end + end + end + + # Executes the given block in a temporary run_context with its own + # resource collection. After the block is executed, any resources + # declared inside are converged, and if any are updated, the + # new_resource will be marked updated. + def recipe_eval_with_update_check(&block) + saved_run_context = @run_context + temp_run_context = @run_context.dup + @run_context = temp_run_context + @run_context.resource_collection = Chef::ResourceCollection.new + + return_value = instance_eval(&block) + Chef::Runner.new(@run_context).converge + return_value + ensure + @run_context = saved_run_context + if temp_run_context.resource_collection.any? {|r| r.updated? } + new_resource.updated_by_last_action(true) + end + end + + end + extend Chef::Mixin::ConvertToClassName extend Chef::Mixin::FromFile @@ -58,6 +100,38 @@ class Chef provider_class end + # Enables inline evaluation of resources in provider actions. + # + # Without this option, any resources declared inside the LWRP are added + # to the resource collection after the current position at the time the + # action is executed. Because they are added to the primary resource + # collection for the chef run, they can notify other resources outside + # the LWRP, and potentially be notified by resources outside the LWRP + # (but this is complicated by the fact that they don't exist until the + # provider executes). In this mode, it is impossible to correctly set the + # updated_by_last_action flag on the parent LWRP resource, since it + # executes and returns before its component resources are run. + # + # With this option enabled, each action creates a temporary run_context + # with its own resource collection, evaluates the action's code in that + # context, and then converges the resources created. If any resources + # were updated, then this provider's new_resource will be marked updated. + # + # In this mode, resources created within the LWRP cannot interact with + # external resources via notifies, though notifications to other + # resources within the LWRP will work. Delayed notifications are executed + # at the conclusion of the provider's action, *not* at the end of the + # main chef run. + # + # This mode of evaluation is experimental, but is believed to be a better + # set of tradeoffs than the append-after mode, so it will likely become + # the default in a future major release of Chef. + # + def self.use_inline_resources + extend InlineResources::ClassMethods + include InlineResources + end + # DSL for defining a provider's actions. def self.action(name, &block) define_method("action_#{name}") do |