summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanielsdeleo <dan@opscode.com>2013-08-01 12:29:12 -0700
committerdanielsdeleo <dan@opscode.com>2013-08-02 09:29:05 -0700
commite4fd4f0e00bc64abb5acf6517593063e2666ea7e (patch)
treef666cde81ea63c59dae13d9361ac8c1684aadec9
parentf3262fc1d1ba12bf31de6dff421c8e77d6692bc7 (diff)
downloadchef-e4fd4f0e00bc64abb5acf6517593063e2666ea7e.tar.gz
Add methods to query for template/file existence in run context
- Convenience methods added to CookbookVersion to query if a cookbook file or template is available for a given node in that cookbook - Convenience methods added to RunContext to query the existence of cookbook files or templates
-rw-r--r--lib/chef/cookbook_version.rb32
-rw-r--r--lib/chef/run_context.rb14
-rw-r--r--spec/support/lib/library_load_order.rb22
-rw-r--r--spec/unit/cookbook_version_spec.rb16
-rw-r--r--spec/unit/run_context/cookbook_compiler_spec.rb18
-rw-r--r--spec/unit/run_context_spec.rb43
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