summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2015-01-20 10:16:17 -0800
committerLamont Granquist <lamont@scriptkiddie.org>2015-01-20 10:21:10 -0800
commit35276fd91c5aec8986723504b8a490e5823b770e (patch)
tree5ea6d3a89ebc905d816753160d290e8a76199e0b
parentb622710cd1ee8af39bc3ff255e2394c0115abaac (diff)
downloadchef-35276fd91c5aec8986723504b8a490e5823b770e.tar.gz
make include_recipe "::foo" use current cookbook
The following code is brittle if you want to fork the cookbook and rename it (which is a best practice when forking cookbooks for internal use): ```ruby if node[:platform_family] == "rhel" include_recipe "mycookbook::_rhel" end ``` In order for cookbooks to be easily renamable they can currently use the syntax `include_recipe "#{cookbook_name}::_rhel"` which is unwieldy. This patch adds `include_recipe "::_rhel"` as syntax sugar to make this easier.
-rw-r--r--lib/chef/dsl/include_recipe.rb5
-rw-r--r--lib/chef/recipe.rb12
-rw-r--r--lib/chef/run_context.rb8
-rw-r--r--spec/unit/recipe_spec.rb28
-rw-r--r--spec/unit/run_context_spec.rb5
5 files changed, 47 insertions, 11 deletions
diff --git a/lib/chef/dsl/include_recipe.rb b/lib/chef/dsl/include_recipe.rb
index fc95e38c75..5ea1075e67 100644
--- a/lib/chef/dsl/include_recipe.rb
+++ b/lib/chef/dsl/include_recipe.rb
@@ -23,11 +23,11 @@ class Chef
module IncludeRecipe
def include_recipe(*recipe_names)
- run_context.include_recipe(*recipe_names)
+ run_context.include_recipe(*recipe_names, current_cookbook: cookbook_name)
end
def load_recipe(recipe_name)
- run_context.load_recipe(recipe_name)
+ run_context.load_recipe(recipe_name, current_cookbook: cookbook_name)
end
def require_recipe(*args)
@@ -42,4 +42,3 @@ end
# **DEPRECATED**
# This used to be part of chef/mixin/language_include_recipe. Load the file to activate the deprecation code.
require 'chef/mixin/language_include_recipe'
-
diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb
index 621d93099b..91f7f30aa9 100644
--- a/lib/chef/recipe.rb
+++ b/lib/chef/recipe.rb
@@ -54,12 +54,16 @@ class Chef
# For example:
# "aws::elastic_ip" returns [:aws, "elastic_ip"]
# "aws" returns [:aws, "default"]
+ # "::elastic_ip" returns [ current_cookbook, "elastic_ip" ]
#--
# TODO: Duplicates functionality of RunListItem
- def self.parse_recipe_name(recipe_name)
- rmatch = recipe_name.match(/(.+?)::(.+)/)
- if rmatch
- [ rmatch[1].to_sym, rmatch[2] ]
+ def self.parse_recipe_name(recipe_name, current_cookbook: nil)
+ case recipe_name
+ when /(.+?)::(.+)/
+ [ $1.to_sym, $2 ]
+ when /^::(.+)/
+ raise "current_cookbook is nil, cannot resolve #{recipe_name}" if current_cookbook.nil?
+ [ current_cookbook.to_sym, $1 ]
else
[ recipe_name.to_sym, "default" ]
end
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index 6803dc5796..bb1bf28ad7 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -136,10 +136,10 @@ class Chef
end
# Evaluates the recipes +recipe_names+. Used by DSL::IncludeRecipe
- def include_recipe(*recipe_names)
+ def include_recipe(*recipe_names, current_cookbook: nil)
result_recipes = Array.new
recipe_names.flatten.each do |recipe_name|
- if result = load_recipe(recipe_name)
+ if result = load_recipe(recipe_name, current_cookbook: current_cookbook)
result_recipes << result
end
end
@@ -147,10 +147,10 @@ class Chef
end
# Evaluates the recipe +recipe_name+. Used by DSL::IncludeRecipe
- def load_recipe(recipe_name)
+ def load_recipe(recipe_name, current_cookbook: nil)
Chef::Log.debug("Loading Recipe #{recipe_name} via include_recipe")
- cookbook_name, recipe_short_name = Chef::Recipe.parse_recipe_name(recipe_name)
+ cookbook_name, recipe_short_name = Chef::Recipe.parse_recipe_name(recipe_name, current_cookbook: current_cookbook)
if unreachable_cookbook?(cookbook_name) # CHEF-4367
Chef::Log.warn(<<-ERROR_MESSAGE)
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index 22389a1a82..5ade7c86e2 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -501,6 +501,34 @@ describe Chef::Recipe do
expect(cookbook_collection[:openldap]).not_to receive(:load_recipe).with("default", run_context)
recipe.include_recipe "openldap"
end
+
+ it "will load a recipe out of the current cookbook when include_recipe is called with a leading ::" do
+ openldap_recipe = Chef::Recipe.new("openldap", "test", run_context)
+ expect(node).to receive(:loaded_recipe).with(:openldap, "default").exactly(:once)
+ allow(run_context).to receive(:unreachable_cookbook?).with(:openldap).and_return(false)
+ expect(cookbook_collection[:openldap]).to receive(:load_recipe).with("default", run_context)
+ openldap_recipe.include_recipe "::default"
+ end
+
+ it "will not include the same recipe twice when using leading :: syntax" do
+ openldap_recipe = Chef::Recipe.new("openldap", "test", run_context)
+ expect(node).to receive(:loaded_recipe).with(:openldap, "default").exactly(:once)
+ allow(run_context).to receive(:unreachable_cookbook?).with(:openldap).and_return(false)
+ expect(cookbook_collection[:openldap]).to receive(:load_recipe).with("default", run_context)
+ openldap_recipe.include_recipe "::default"
+ expect(cookbook_collection[:openldap]).not_to receive(:load_recipe).with("default", run_context)
+ openldap_recipe.include_recipe "openldap::default"
+ end
+
+ it "will not include the same recipe twice when using leading :: syntax (reversed order)" do
+ openldap_recipe = Chef::Recipe.new("openldap", "test", run_context)
+ expect(node).to receive(:loaded_recipe).with(:openldap, "default").exactly(:once)
+ allow(run_context).to receive(:unreachable_cookbook?).with(:openldap).and_return(false)
+ expect(cookbook_collection[:openldap]).to receive(:load_recipe).with("default", run_context)
+ openldap_recipe.include_recipe "openldap::default"
+ expect(cookbook_collection[:openldap]).not_to receive(:load_recipe).with("default", run_context)
+ openldap_recipe.include_recipe "::default"
+ end
end
describe "tags" do
diff --git a/spec/unit/run_context_spec.rb b/spec/unit/run_context_spec.rb
index ba4f2ede68..d656111a7d 100644
--- a/spec/unit/run_context_spec.rb
+++ b/spec/unit/run_context_spec.rb
@@ -104,6 +104,11 @@ describe Chef::RunContext do
end.to raise_error(Chef::Exceptions::CookbookNotFound)
end
+ it "raises an error on a recipe with a leading :: with no current_cookbook" do
+ expect do
+ run_context.include_recipe("::aliens")
+ end.to raise_error(RuntimeError)
+ end
end
describe "querying the contents of cookbooks" do