diff options
-rw-r--r-- | lib/chef/cookbook_version.rb | 32 | ||||
-rw-r--r-- | lib/chef/run_context.rb | 14 | ||||
-rw-r--r-- | spec/support/lib/library_load_order.rb | 22 | ||||
-rw-r--r-- | spec/unit/cookbook_version_spec.rb | 16 | ||||
-rw-r--r-- | spec/unit/run_context/cookbook_compiler_spec.rb | 18 | ||||
-rw-r--r-- | spec/unit/run_context_spec.rb | 43 |
6 files changed, 119 insertions, 26 deletions
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb index 4e8b2a048e..5bd0ca064c 100644 --- a/lib/chef/cookbook_version.rb +++ b/lib/chef/cookbook_version.rb @@ -265,6 +265,18 @@ class Chef end end + # Query whether a template file +template_filename+ is available. File + # specificity for the given +node+ is obeyed in the lookup. + def has_template_for_node?(node, template_filename) + !!find_preferred_manifest_record(node, :templates, template_filename) + end + + # Query whether a cookbook_file file +cookbook_filename+ is available. File + # specificity for the given +node+ is obeyed in the lookup. + def has_cookbook_file_for_node?(node, cookbook_filename) + !!find_preferred_manifest_record(node, :files, cookbook_filename) + end + # Determine the most specific manifest record for the given # segment/filename, given information in the node. Throws # FileNotFound if there is no such segment and filename in the @@ -278,14 +290,7 @@ class Chef # :checksum => "1234" # } def preferred_manifest_record(node, segment, filename) - preferences = preferences_for_path(node, segment, filename) - - # ensure that we generate the manifest, which will also generate - # @manifest_records_by_path - manifest - - # in order of prefernce, look for the filename in the manifest - found_pref = preferences.find {|preferred_filename| @manifest_records_by_path[preferred_filename] } + found_pref = find_preferred_manifest_record(node, segment, filename) if found_pref @manifest_records_by_path[found_pref] else @@ -567,6 +572,17 @@ class Chef private + def find_preferred_manifest_record(node, segment, filename) + preferences = preferences_for_path(node, segment, filename) + + # ensure that we generate the manifest, which will also generate + # @manifest_records_by_path + manifest + + # in order of prefernce, look for the filename in the manifest + preferences.find {|preferred_filename| @manifest_records_by_path[preferred_filename] } + end + # For each filename, produce a mapping of base filename (i.e. recipe name # or attribute file) to on disk location def filenames_by_name(filenames) diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb index 6477431967..4d431116f9 100644 --- a/lib/chef/run_context.rb +++ b/lib/chef/run_context.rb @@ -204,6 +204,20 @@ class Chef @loaded_attributes["#{cookbook}::#{attribute_file}"] = true end + ## + # Cookbook File Introspection + + def has_template_in_cookbook?(cookbook, template_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_template_for_node?(node, template_name) + end + + def has_cookbook_file_in_cookbook?(cookbook, cb_file_name) + cookbook = cookbook_collection[cookbook] + cookbook.has_cookbook_file_for_node?(node, cb_file_name) + end + + private def loaded_recipe(cookbook, recipe) diff --git a/spec/support/lib/library_load_order.rb b/spec/support/lib/library_load_order.rb new file mode 100644 index 0000000000..c47a2f2c74 --- /dev/null +++ b/spec/support/lib/library_load_order.rb @@ -0,0 +1,22 @@ +# Helper module to track the load order of library files. +# Used by `cookbook_compiler_spec.rb` +# +# This module must be loaded for any tests that load the cookbook +# data/run_context/cookbooks/test to succeed. +module LibraryLoadOrder + extend self + + def load_order + @load_order ||= [] + end + + def reset! + @load_order = nil + end + + def record(file) + load_order << file + end +end + + diff --git a/spec/unit/cookbook_version_spec.rb b/spec/unit/cookbook_version_spec.rb index 85e1db1fae..d186ef01be 100644 --- a/spec/unit/cookbook_version_spec.rb +++ b/spec/unit/cookbook_version_spec.rb @@ -130,6 +130,12 @@ describe Chef::CookbookVersion do @cookbook_version.provider_filenames = @cookbook[:provider_filenames] @cookbook_version.root_filenames = @cookbook[:root_filenames] @cookbook_version.metadata_filenames = @cookbook[:metadata_filenames] + + # Used to test file-specificity related file lookups + @node = Chef::Node.new + @node.set[:platform] = "ubuntu" + @node.set[:platform_version] = "13.04" + @node.name("testing") end it "generates a manifest containing the cookbook's files" do @@ -211,6 +217,16 @@ describe Chef::CookbookVersion do readme["specificity"].should == "default" end + it "determines whether a template is available for a given node" do + @cookbook_version.should have_template_for_node(@node, "configuration.erb") + @cookbook_version.should_not have_template_for_node(@node, "missing.erb") + end + + it "determines whether a cookbook_file is available for a given node" do + @cookbook_version.should have_cookbook_file_for_node(@node, "giant_blob.tgz") + @cookbook_version.should_not have_cookbook_file_for_node(@node, "missing.txt") + end + describe "raises an error when attempting to load a missing cookbook_file and" do before do node = Chef::Node.new.tap do |n| diff --git a/spec/unit/run_context/cookbook_compiler_spec.rb b/spec/unit/run_context/cookbook_compiler_spec.rb index 0c5e568a13..fe6bef5618 100644 --- a/spec/unit/run_context/cookbook_compiler_spec.rb +++ b/spec/unit/run_context/cookbook_compiler_spec.rb @@ -17,23 +17,7 @@ # require 'spec_helper' - -# Keeps track of what file got loaded in what order. -module LibraryLoadOrder - extend self - - def load_order - @load_order ||= [] - end - - def reset! - @load_order = nil - end - - def record(file) - load_order << file - end -end +require 'support/lib/library_load_order' # These tests rely on fixture data in spec/data/run_context/cookbooks. # diff --git a/spec/unit/run_context_spec.rb b/spec/unit/run_context_spec.rb index 51fa0e81f9..d75d6628bb 100644 --- a/spec/unit/run_context_spec.rb +++ b/spec/unit/run_context_spec.rb @@ -19,6 +19,7 @@ # require 'spec_helper' +require 'support/lib/library_load_order' Chef::Log.level = :debug @@ -42,7 +43,7 @@ describe Chef::RunContext do @run_context.node.should == @node end - describe "after loading the cookbooks" do + describe "loading cookbooks for a run list" do before do @run_context.load(@node.run_list.expand('_default')) end @@ -73,6 +74,46 @@ describe Chef::RunContext do @node.should_not_receive(:from_file) @node.include_attribute("test::george") end + + + end + + describe "querying the contents of cookbooks" do + before do + @chef_repo_path = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) + cl = Chef::CookbookLoader.new(@chef_repo_path) + cl.load_cookbooks + @cookbook_collection = Chef::CookbookCollection.new(cl) + @node = Chef::Node.new + @node.set[:platform] = "ubuntu" + @node.set[:platform_version] = "13.04" + @node.name("testing") + @events = Chef::EventDispatch::Dispatcher.new + @run_context = Chef::RunContext.new(@node, @cookbook_collection, @events) + end + + + it "queries whether a given cookbook has a specific template" do + @run_context.should have_template_in_cookbook("openldap", "test.erb") + @run_context.should_not have_template_in_cookbook("openldap", "missing.erb") + end + + it "errors when querying for a template in a not-available cookbook" do + expect do + @run_context.has_template_in_cookbook?("no-such-cookbook", "foo.erb") + end.to raise_error(Chef::Exceptions::CookbookNotFound) + end + + it "queries whether a given cookbook has a specific cookbook_file" do + @run_context.should have_cookbook_file_in_cookbook("java", "java.response") + @run_context.should_not have_cookbook_file_in_cookbook("java", "missing.txt") + end + + it "errors when querying for a cookbook_file in a not-available cookbook" do + expect do + @run_context.has_cookbook_file_in_cookbook?("no-such-cookbook", "foo.txt") + end.to raise_error(Chef::Exceptions::CookbookNotFound) + end end end |