diff options
-rw-r--r-- | lib/chef/dsl/include_recipe.rb | 5 | ||||
-rw-r--r-- | lib/chef/recipe.rb | 12 | ||||
-rw-r--r-- | lib/chef/run_context.rb | 8 | ||||
-rw-r--r-- | spec/unit/recipe_spec.rb | 28 | ||||
-rw-r--r-- | spec/unit/run_context_spec.rb | 5 |
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 |