summaryrefslogtreecommitdiff
path: root/lib/chef/provider/lwrp_base.rb
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2012-12-20 08:33:33 -0800
committerdanielsdeleo <dan@opscode.com>2012-12-27 09:37:44 -0700
commit88f3c2703c1a9faaa65e94c1f56260eda22982e4 (patch)
tree40dad61a4e7fe79b73d4bd1926f5f10944da3d24 /lib/chef/provider/lwrp_base.rb
parentf132b98c4faddcaee5002105a6aa647bbb549c19 (diff)
downloadchef-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.rb74
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