summaryrefslogtreecommitdiff
path: root/lib/chef/dsl
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2014-01-31 16:44:48 -0800
committerdanielsdeleo <dan@opscode.com>2014-02-03 17:08:54 -0800
commitb4c8facbf495423950345937ab4a8d6d8792ad16 (patch)
tree6ef2f4bc852b4ee3e2080f612dd9b43921f1e9ac /lib/chef/dsl
parent040865b55964056d3249de896baafe60587f5105 (diff)
downloadchef-b4c8facbf495423950345937ab4a8d6d8792ad16.tar.gz
Expose resource creation via more static methods
Diffstat (limited to 'lib/chef/dsl')
-rw-r--r--lib/chef/dsl/recipe.rb136
1 files changed, 98 insertions, 38 deletions
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index f3507a8031..a1bdd9d665 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -31,53 +31,113 @@ class Chef
include Chef::Mixin::ConvertToClassName
+ # Default +cookbook_name+ implementation, always returns "none". This
+ # should be overriden in including classes whenever a meaningful value
+ # can be provided.
+ def cookbook_name
+ "none"
+ end
+
+ # Default +recipe_name+ implementation, always returns "none". This
+ # should be overridden in including classes whenever a meaningful value
+ # can be provided.
+ def recipe_name
+ "none"
+ end
+
def method_missing(method_symbol, *args, &block)
# If we have a definition that matches, we want to use that instead. This should
# let you do some really crazy over-riding of "native" types, if you really want
# to.
- if run_context.definitions.has_key?(method_symbol)
- # This dupes the high level object, but we still need to dup the params
- new_def = run_context.definitions[method_symbol].dup
- new_def.params = new_def.params.dup
- new_def.node = run_context.node
- # This sets up the parameter overrides
- new_def.instance_eval(&block) if block
- new_recipe = Chef::Recipe.new(cookbook_name, @recipe_name, run_context)
- new_recipe.params = new_def.params
- new_recipe.params[:name] = args[0]
- new_recipe.instance_eval(&new_def.recipe)
+ if has_resource_definition?(method_symbol)
+ evaluate_resource_definition(method_symbol, *args, &block)
else
# Otherwise, we're rocking the regular resource call route.
-
- # Checks the new platform => short_name => resource mapping initially
- # then fall back to the older approach (Chef::Resource.const_get) for
- # backward compatibility
- resource_class = Chef::Resource.resource_for_node(method_symbol, run_context.node)
-
- super unless resource_class
- raise ArgumentError, "You must supply a name when declaring a #{method_symbol} resource" unless args.size > 0
-
- # If we have a resource like this one, we want to steal its state
- args << run_context
- resource = resource_class.new(*args)
- resource.source_line = caller[0]
- resource.load_prior_resource
- resource.cookbook_name = cookbook_name
- resource.recipe_name = @recipe_name
- resource.params = @params
- # Determine whether this resource is being created in the context of an enclosing Provider
- resource.enclosing_provider = self.is_a?(Chef::Provider) ? self : nil
- # Evaluate resource attribute DSL
- resource.instance_eval(&block) if block
-
- # Run optional resource hook
- resource.after_created
-
- run_context.resource_collection.insert(resource)
- resource
+ declare_resource(method_symbol, args[0], caller[0], &block)
end
end
+ def has_resource_definition?(name)
+ yes_or_no = run_context.definitions.has_key?(name)
+
+ yes_or_no
+ end
+
+ # Processes the arguments and block as a resource definition.
+ def evaluate_resource_definition(definition_name, *args, &block)
+
+ # This dupes the high level object, but we still need to dup the params
+ new_def = run_context.definitions[definition_name].dup
+
+ new_def.params = new_def.params.dup
+ new_def.node = run_context.node
+ # This sets up the parameter overrides
+ new_def.instance_eval(&block) if block
+
+
+ new_recipe = Chef::Recipe.new(cookbook_name, recipe_name, run_context)
+ new_recipe.params = new_def.params
+ new_recipe.params[:name] = args[0]
+ new_recipe.instance_eval(&new_def.recipe)
+ new_recipe
+ end
+
+ # Instantiates a resource (via #build_resource), then adds it to the
+ # resource collection. Note that resource classes are looked up directly,
+ # so this will create the resource you intended even if the method name
+ # corresponding to that resource has been overridden.
+ def declare_resource(type, name, created_at=nil, &resource_attrs_block)
+ created_at ||= caller[0]
+
+ resource = build_resource(type, name, created_at, &resource_attrs_block)
+
+ run_context.resource_collection.insert(resource)
+ resource
+ end
+
+ # Instantiate a resource of the given +type+ with the given +name+ and
+ # attributes as given in the +resource_attrs_block+.
+ #
+ # The resource is NOT added to the resource collection.
+ def build_resource(type, name, created_at=nil, &resource_attrs_block)
+ created_at ||= caller[0]
+
+ # Checks the new platform => short_name => resource mapping initially
+ # then fall back to the older approach (Chef::Resource.const_get) for
+ # backward compatibility
+ resource_class = resource_class_for(type)
+
+ super unless resource_class
+ raise ArgumentError, "You must supply a name when declaring a #{type} resource" if name.nil?
+
+ resource = resource_class.new(name, run_context)
+ resource.source_line = created_at
+ resource.cookbook_name = cookbook_name
+ resource.recipe_name = recipe_name
+ # If we have a resource like this one, we want to steal its state
+ # This behavior is very counter-intuitive and should be removed.
+ # See CHEF-3694, https://tickets.opscode.com/browse/CHEF-3694
+ resource.load_prior_resource
+ # Determine whether this resource is being created in the context of an enclosing Provider
+ resource.enclosing_provider = self.is_a?(Chef::Provider) ? self : nil
+
+ # XXX: This is very crufty, but it's required for resource definitions
+ # to work properly :(
+ resource.params = @params
+
+ # Evaluate resource attribute DSL
+ resource.instance_eval(&resource_attrs_block) if block_given?
+
+ # Run optional resource hook
+ resource.after_created
+
+ resource
+ end
+
+ def resource_class_for(snake_case_name)
+ Chef::Resource.resource_for_node(snake_case_name, run_context.node)
+ end
+
end
end
end