diff options
24 files changed, 319 insertions, 417 deletions
diff --git a/chef/lib/chef/client.rb b/chef/lib/chef/client.rb index fd673545f3..cd7a513a23 100644 --- a/chef/lib/chef/client.rb +++ b/chef/lib/chef/client.rb @@ -9,9 +9,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -126,7 +126,7 @@ class Chef @runner = nil @ohai = Ohai::System.new end - + # Do a full run for this Chef::Client. Calls: # # * run_ohai - Collect information about the system @@ -143,13 +143,13 @@ class Chef run_ohai register unless Chef::Config[:solo] build_node - + begin run_status.start_clock Chef::Log.info("Starting Chef Run (Version #{Chef::VERSION})") run_started - + run_context = setup_run_context converge(run_context) save_updated_node @@ -178,8 +178,8 @@ class Chef # Chef::RunContext:: the run context for this run. def setup_run_context if Chef::Config[:solo] - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } - run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(Chef::CookbookLoader.new)) + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, Chef::Config[:cookbook_path]) } + run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new(Chef::CookbookLoader.new(Chef::Config[:cookbook_path]))) else Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, rest) } cookbook_hash = sync_cookbooks @@ -213,7 +213,7 @@ class Chef name end - + # Builds a new node object for this client. Starts with querying for the FQDN of the current # host (unless it is supplied), then merges in the facts from Ohai. # @@ -248,22 +248,22 @@ class Chef # @run_list_expansion is a RunListExpansion. # # Convert @expanded_run_list, which is an - # Array of Hashes of the form + # Array of Hashes of the form # {:name => NAME, :version_constraint => Chef::VersionConstraint }, - # into @expanded_run_list_with_versions, an + # into @expanded_run_list_with_versions, an # Array of Strings of the form # "#{NAME}@#{VERSION}" @expanded_run_list_with_versions = @run_list_expansion.recipes.with_version_constraints_strings Chef::Log.info("Run List is [#{@node.run_list}]") Chef::Log.info("Run List expands (with versions) to [#{@expanded_run_list_with_versions.join(', ')}]") - + @run_status = Chef::RunStatus.new(@node) @node end - # + # # === Returns # rest<Chef::REST>:: returns Chef::REST connection object def register @@ -276,7 +276,7 @@ class Chef # We now have the client key, and should use it from now on. self.rest = Chef::REST.new(Chef::Config[:chef_server_url], node_name, Chef::Config[:client_key]) end - + # Sync_cookbooks eagerly loads all files except files and # templates. It returns the cookbook_hash -- the return result # from /environments/#{node.chef_environment}/cookbook_versions, @@ -292,10 +292,10 @@ class Chef # register the file cache path in the cookbook path so that CookbookLoader actually picks up the synced cookbooks Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks") - + cookbook_hash end - + # Converges the node. # # === Returns @@ -306,23 +306,23 @@ class Chef runner.converge true end - + private - + def directory_not_empty?(path) File.exists?(path) && (Dir.entries(path).size > 2) end - + def is_last_element?(index, object) - object.kind_of?(Array) ? index == object.size - 1 : true - end - + object.kind_of?(Array) ? index == object.size - 1 : true + end + def assert_cookbook_path_not_empty(run_context) if Chef::Config[:solo] # Check for cookbooks in the path given # Chef::Config[:cookbook_path] can be a string or an array # if it's an array, go through it and check each one, raise error at the last one if no files are found - Chef::Log.debug "loading from cookbook_path: #{Array(Chef::Config[:cookbook_path]).map { |path| File.expand_path(path) }.join(', ')}" + Chef::Log.debug "loading from cookbook_path: #{Array(Chef::Config[:cookbook_path]).map { |path| File.expand_path(path) }.join(', ')}" Array(Chef::Config[:cookbook_path]).each_with_index do |cookbook_path, index| if directory_not_empty?(cookbook_path) break diff --git a/chef/lib/chef/cookbook/cookbook_collection.rb b/chef/lib/chef/cookbook/cookbook_collection.rb index 9527ccde14..ae63abfc93 100644 --- a/chef/lib/chef/cookbook/cookbook_collection.rb +++ b/chef/lib/chef/cookbook/cookbook_collection.rb @@ -7,9 +7,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -40,6 +40,6 @@ class Chef end cookbook_versions.each{ |cookbook_name, cookbook_version| self[cookbook_name] = cookbook_version } end - + end end diff --git a/chef/lib/chef/cookbook/file_system_file_vendor.rb b/chef/lib/chef/cookbook/file_system_file_vendor.rb index 166ab2510c..8896e3ed30 100644 --- a/chef/lib/chef/cookbook/file_system_file_vendor.rb +++ b/chef/lib/chef/cookbook/file_system_file_vendor.rb @@ -7,9 +7,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,25 +30,27 @@ class Chef # locations, since in the chef-client case, that information is # non-sensical. class FileSystemFileVendor < FileVendor - - def initialize(manifest) + + def initialize(manifest, *repo_paths) @cookbook_name = manifest[:cookbook_name] + @repo_paths = repo_paths.flatten + raise ArgumentError, "You must specify at least one repo path" if @repo_paths.empty? end - + # Implements abstract base's requirement. It looks in the # Chef::Config.cookbook_path file hierarchy for the requested # file. def get_filename(filename) - location = Array(Chef::Config.cookbook_path).inject(nil) do |memo, basepath| + location = @repo_paths.inject(nil) do |memo, basepath| candidate_location = File.join(basepath, @cookbook_name, filename) memo = candidate_location if File.exist?(candidate_location) memo end raise "File #{filename} does not exist for cookbook #{@cookbook_name}" unless location - + location end - + end end end diff --git a/chef/lib/chef/cookbook_loader.rb b/chef/lib/chef/cookbook_loader.rb index 15d0f7779e..56bb9092a5 100644 --- a/chef/lib/chef/cookbook_loader.rb +++ b/chef/lib/chef/cookbook_loader.rb @@ -32,7 +32,9 @@ class Chef include Enumerable - def initialize() + def initialize(*repo_paths) + @repo_paths = repo_paths.flatten + raise ArgumentError, "You must specify at least one cookbook repo path" if @repo_paths.empty? @cookbooks_by_name = Mash.new @loaded_cookbooks = {} @metadata = Mash.new @@ -41,7 +43,7 @@ class Chef def load_cookbooks cookbook_settings = Hash.new - Array(Chef::Config.cookbook_path).each do |repo_path| + @repo_paths.each do |repo_path| repo_path = File.expand_path(repo_path) chefignore = Cookbook::Chefignore.new(repo_path) Dir[File.join(repo_path, "*")].each do |cookbook_path| diff --git a/chef/lib/chef/cookbook_uploader.rb b/chef/lib/chef/cookbook_uploader.rb index b8ac2e6aa3..20c21cfd69 100644 --- a/chef/lib/chef/cookbook_uploader.rb +++ b/chef/lib/chef/cookbook_uploader.rb @@ -8,96 +8,101 @@ require 'chef/cookbook/file_system_file_vendor' class Chef class CookbookUploader - class << self - def upload_cookbook(cookbook) - Chef::Log.info("Saving #{cookbook.name}") + attr_reader :cookbook + attr_reader :path - rest = Chef::REST.new(Chef::Config[:chef_server_url]) + def initialize(cookbook, path) + @cookbook, @path = cookbook, path + end - # Syntax Check - validate_cookbook(cookbook) - # Generate metadata.json from metadata.rb - build_metadata(cookbook) + def upload_cookbook + Chef::Log.info("Saving #{cookbook.name}") - # generate checksums of cookbook files and create a sandbox - checksum_files = cookbook.checksums - checksums = checksum_files.inject({}){|memo,elt| memo[elt.first]=nil ; memo} - new_sandbox = rest.post_rest("sandboxes", { :checksums => checksums }) + rest = Chef::REST.new(Chef::Config[:chef_server_url]) - Chef::Log.info("Uploading files") - # upload the new checksums and commit the sandbox - new_sandbox['checksums'].each do |checksum, info| - if info['needs_upload'] == true - Chef::Log.info("Uploading #{checksum_files[checksum]} (checksum hex = #{checksum}) to #{info['url']}") + # Syntax Check + validate_cookbook + # Generate metadata.json from metadata.rb + build_metadata - # Checksum is the hexadecimal representation of the md5, - # but we need the base64 encoding for the content-md5 - # header - checksum64 = Base64.encode64([checksum].pack("H*")).strip - timestamp = Time.now.utc.iso8601 - file_contents = File.read(checksum_files[checksum]) - # TODO - 5/28/2010, cw: make signing and sending the request streaming - sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object( - :http_method => :put, - :path => URI.parse(info['url']).path, - :body => file_contents, - :timestamp => timestamp, - :user_id => rest.client_name - ) - headers = { 'content-type' => 'application/x-binary', 'content-md5' => checksum64, :accept => 'application/json' } - headers.merge!(sign_obj.sign(OpenSSL::PKey::RSA.new(rest.signing_key))) - begin - RestClient::Resource.new(info['url'], :headers=>headers, :timeout=>1800, :open_timeout=>1800).put(file_contents) - rescue RestClient::Exception => e - Chef::Log.error("Upload failed: #{e.message}\n#{e.response.body}") - raise - end - else - Chef::Log.debug("#{checksum_files[checksum]} has not changed") - end - end - sandbox_url = new_sandbox['uri'] - Chef::Log.debug("Committing sandbox") - # Retry if S3 is claims a checksum doesn't exist (the eventual - # in eventual consistency) - retries = 0 - begin - rest.put_rest(sandbox_url, {:is_completed => true}) - rescue Net::HTTPServerException => e - if e.message =~ /^400/ && (retries += 1) <= 5 - sleep 2 - retry - else + # generate checksums of cookbook files and create a sandbox + checksum_files = cookbook.checksums + checksums = checksum_files.inject({}){|memo,elt| memo[elt.first]=nil ; memo} + new_sandbox = rest.post_rest("sandboxes", { :checksums => checksums }) + + Chef::Log.info("Uploading files") + # upload the new checksums and commit the sandbox + new_sandbox['checksums'].each do |checksum, info| + if info['needs_upload'] == true + Chef::Log.info("Uploading #{checksum_files[checksum]} (checksum hex = #{checksum}) to #{info['url']}") + + # Checksum is the hexadecimal representation of the md5, + # but we need the base64 encoding for the content-md5 + # header + checksum64 = Base64.encode64([checksum].pack("H*")).strip + timestamp = Time.now.utc.iso8601 + file_contents = File.read(checksum_files[checksum]) + # TODO - 5/28/2010, cw: make signing and sending the request streaming + sign_obj = Mixlib::Authentication::SignedHeaderAuth.signing_object( + :http_method => :put, + :path => URI.parse(info['url']).path, + :body => file_contents, + :timestamp => timestamp, + :user_id => rest.client_name + ) + headers = { 'content-type' => 'application/x-binary', 'content-md5' => checksum64, :accept => 'application/json' } + headers.merge!(sign_obj.sign(OpenSSL::PKey::RSA.new(rest.signing_key))) + begin + RestClient::Resource.new(info['url'], :headers=>headers, :timeout=>1800, :open_timeout=>1800).put(file_contents) + rescue RestClient::Exception => e + Chef::Log.error("Upload failed: #{e.message}\n#{e.response.body}") raise end + else + Chef::Log.debug("#{checksum_files[checksum]} has not changed") end - # files are uploaded, so save the manifest - cookbook.save - Chef::Log.info("Upload complete!") end - - def build_metadata(cookbook) - Chef::Log.debug("Generating metadata") - # FIXME: This knife command should be factored out into a - # library for use here - kcm = Chef::Knife::CookbookMetadata.new - kcm.config[:cookbook_path] = Chef::Config[:cookbook_path] - kcm.name_args = [ cookbook.name.to_s ] - kcm.run - cookbook.reload_metadata! + sandbox_url = new_sandbox['uri'] + Chef::Log.debug("Committing sandbox") + # Retry if S3 is claims a checksum doesn't exist (the eventual + # in eventual consistency) + retries = 0 + begin + rest.put_rest(sandbox_url, {:is_completed => true}) + rescue Net::HTTPServerException => e + if e.message =~ /^400/ && (retries += 1) <= 5 + sleep 2 + retry + else + raise + end end + # files are uploaded, so save the manifest + cookbook.save + Chef::Log.info("Upload complete!") + end - def validate_cookbook(cookbook) - syntax_checker = Chef::Cookbook::SyntaxCheck.for_cookbook(cookbook.name, @user_cookbook_path) - Chef::Log.info("Validating ruby files") - exit(1) unless syntax_checker.validate_ruby_files - Chef::Log.info("Validating templates") - exit(1) unless syntax_checker.validate_templates - Chef::Log.info("Syntax OK") - true - end + def build_metadata + Chef::Log.debug("Generating metadata") + # FIXME: This knife command should be factored out into a + # library for use here + kcm = Chef::Knife::CookbookMetadata.new + kcm.config[:cookbook_path] = path + kcm.name_args = [ cookbook.name.to_s ] + kcm.run + cookbook.reload_metadata! + end + def validate_cookbook + syntax_checker = Chef::Cookbook::SyntaxCheck.for_cookbook(cookbook.name, @user_cookbook_path) + Chef::Log.info("Validating ruby files") + exit(1) unless syntax_checker.validate_ruby_files + Chef::Log.info("Validating templates") + exit(1) unless syntax_checker.validate_templates + Chef::Log.info("Syntax OK") + true end + end end diff --git a/chef/lib/chef/knife/cookbook_metadata.rb b/chef/lib/chef/knife/cookbook_metadata.rb index 052756560b..0613c69889 100644 --- a/chef/lib/chef/knife/cookbook_metadata.rb +++ b/chef/lib/chef/knife/cookbook_metadata.rb @@ -37,14 +37,10 @@ class Chef :description => "Generate metadata for all cookbooks, rather than just a single cookbook" def run - if config[:cookbook_path] - Chef::Config[:cookbook_path] = config[:cookbook_path] - else - config[:cookbook_path] = Chef::Config[:cookbook_path] - end + config[:cookbook_path] ||= Chef::Config[:cookbook_path] if config[:all] - cl = Chef::CookbookLoader.new + cl = Chef::CookbookLoader.new(config[:cookbook_path]) cl.each do |cname, cookbook| generate_metadata(cname.to_s) end diff --git a/chef/lib/chef/knife/cookbook_site_share.rb b/chef/lib/chef/knife/cookbook_site_share.rb index f881851341..791013a787 100644 --- a/chef/lib/chef/knife/cookbook_site_share.rb +++ b/chef/lib/chef/knife/cookbook_site_share.rb @@ -40,9 +40,11 @@ class Chef exit 1 end + config[:cookbook_path] ||= Chef::Config[:cookbook_path] + cookbook_name = @name_args[0] category = @name_args[1] - cl = Chef::CookbookLoader.new + cl = Chef::CookbookLoader.new(config[:cookbook_path]) if cl.cookbook_exists?(cookbook_name) cookbook = cl[cookbook_name] Chef::CookbookUploader.validate_cookbook(cookbook) diff --git a/chef/lib/chef/knife/cookbook_test.rb b/chef/lib/chef/knife/cookbook_test.rb index 9e90da746d..2b46cec2b8 100644 --- a/chef/lib/chef/knife/cookbook_test.rb +++ b/chef/lib/chef/knife/cookbook_test.rb @@ -9,9 +9,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -38,15 +38,11 @@ class Chef :long => "--all", :description => "Test all cookbooks, rather than just a single cookbook" - def run - if config[:cookbook_path] - Chef::Config[:cookbook_path] = config[:cookbook_path] - else - config[:cookbook_path] = Chef::Config[:cookbook_path] - end + def run + config[:cookbook_path] ||= Chef::Config[:cookbook_path] if config[:all] - cl = Chef::CookbookLoader.new + cl = Chef::CookbookLoader.new(config[:cookbook_path]) cl.each do |key, cookbook| test_cookbook(key) end @@ -71,7 +67,7 @@ class Chef Chef::Log.info("Validating ruby files") exit(1) unless syntax_checker.validate_ruby_files end - + def test_templates(syntax_checker) Chef::Log.info("Validating templates") exit(1) unless syntax_checker.validate_templates diff --git a/chef/lib/chef/knife/cookbook_upload.rb b/chef/lib/chef/knife/cookbook_upload.rb index 52162fa616..a2c4b971db 100644 --- a/chef/lib/chef/knife/cookbook_upload.rb +++ b/chef/lib/chef/knife/cookbook_upload.rb @@ -39,22 +39,18 @@ class Chef :long => "--all", :description => "Upload all cookbooks, rather than just a single cookbook" - def run - if config[:cookbook_path] - Chef::Config[:cookbook_path] = config[:cookbook_path] - else - config[:cookbook_path] = Chef::Config[:cookbook_path] - end + def run + config[:cookbook_path] ||= Chef::Config[:cookbook_path] - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, config[:cookbook_path]) } - cl = Chef::CookbookLoader.new + cl = Chef::CookbookLoader.new(config[:cookbook_path]) humanize_auth_exceptions do if config[:all] cl.each do |cookbook_name, cookbook| Chef::Log.info("** #{cookbook.name.to_s} **") - Chef::CookbookUploader.upload_cookbook(cookbook) + Chef::CookbookUploader.new(cookbook, config[:cookbook_path]).upload_cookbook end else if @name_args.length < 1 @@ -64,7 +60,7 @@ class Chef end @name_args.each do |cookbook_name| if cl.cookbook_exists?(cookbook_name) - Chef::CookbookUploader.upload_cookbook(cl[cookbook_name]) + Chef::CookbookUploader.new(cl[cookbook_name], config[:cookbook_path]).upload_cookbook else Chef::Log.error("Could not find cookbook #{cookbook_name} in your cookbook path, skipping it") end diff --git a/chef/lib/chef/mixin/find_preferred_file.rb b/chef/lib/chef/mixin/find_preferred_file.rb deleted file mode 100644 index e802b2c565..0000000000 --- a/chef/lib/chef/mixin/find_preferred_file.rb +++ /dev/null @@ -1,92 +0,0 @@ -# -# Author:: Adam Jacob (<adam@opscode.com>) -# Copyright:: Copyright (c) 2008 Opscode, Inc. -# License:: Apache License, Version 2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'chef/cookbook_loader' - -class Chef - module Mixin - module FindPreferredFile - - def load_cookbook_files(cookbook_id, file_type) - unless file_type == :remote_file || file_type == :template - raise ArgumentError, "You must supply :remote_file or :template as the file_type" - end - - cl = Chef::CookbookLoader.new - cookbook = cl[cookbook_id] - raise NotFound unless cookbook - - files = Hash.new - - cookbook_method = nil - - case file_type - when :remote_file - cookbook_method = :remote_files - when :template - cookbook_method = :template_files - end - - cookbook.send(cookbook_method).each do |rf| - full = File.expand_path(rf) - name = File.basename(full) - case file_type - when :remote_file - rf =~ /^.+#{Regexp.escape(cookbook_id)}[\\|\/]files[\\|\/](.+?)[\\|\/]#{Regexp.escape(name)}/ - when :template - rf =~ /^.+#{Regexp.escape(cookbook_id)}[\\|\/]templates[\\|\/](.+?)[\\|\/]#{Regexp.escape(name)}/ - end - singlecopy = $1 - files[full] = { - :name => name, - :singlecopy => singlecopy, - :file => full, - } - end - Chef::Log.debug("Preferred #{file_type} list: #{files.inspect}") - - files - end - - def find_preferred_file(cookbook_id, file_type, file_name, fqdn, platform, version) - file_list = load_cookbook_files(cookbook_id, file_type) - - preferences = [ - File.join("host-#{fqdn}", "#{file_name}"), - File.join("#{platform}-#{version}", "#{file_name}"), - File.join("#{platform}", "#{file_name}"), - File.join("default", "#{file_name}") - ] - - file_list_str = file_list.keys.join("\n") - Chef::Log.debug("Searching for preferred file in\n#{file_list_str}") - - preferences.each do |pref| - Chef::Log.debug("Looking for #{pref}") - matcher = /^(.+#{Regexp.escape(pref)})$/ - if match = matcher.match(file_list_str) - return match[1] - end - end - - raise Chef::Exceptions::FileNotFound, "Cannot find a preferred file for #{file_name}!" - end - - end - end -end diff --git a/chef/lib/chef/shef/shef_session.rb b/chef/lib/chef/shef/shef_session.rb index 4a088b2e5a..b5fcd76b89 100644 --- a/chef/lib/chef/shef/shef_session.rb +++ b/chef/lib/chef/shef/shef_session.rb @@ -161,8 +161,8 @@ module Shef end def rebuild_context - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } - @run_context = Chef::RunContext.new(@node, Chef::CookbookCollection.new(Chef::CookbookLoader.new)) + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, Chef::Config[:cookbook_path]) } + @run_context = Chef::RunContext.new(@node, Chef::CookbookCollection.new(Chef::CookbookLoader.new(Chef::Config[:cookbook_path]))) @run_context.load(Chef::RunList::RunListExpansionFromDisk.new("_default", [])) run_status.run_context = run_context end diff --git a/chef/spec/unit/cookbook_loader_spec.rb b/chef/spec/unit/cookbook_loader_spec.rb index 65fac00f1f..97c1ccab8f 100644 --- a/chef/spec/unit/cookbook_loader_spec.rb +++ b/chef/spec/unit/cookbook_loader_spec.rb @@ -20,11 +20,9 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) describe Chef::CookbookLoader do before(:each) do - Chef::Config.cookbook_path [ - File.expand_path(File.join(CHEF_SPEC_DATA, "kitchen")), - File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) - ] - @cookbook_loader = Chef::CookbookLoader.new() + @repo_paths = [ File.expand_path(File.join(CHEF_SPEC_DATA, "kitchen")), + File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) ] + @cookbook_loader = Chef::CookbookLoader.new(@repo_paths) end describe "[]" do diff --git a/chef/spec/unit/cookbook_spec.rb b/chef/spec/unit/cookbook_spec.rb index 8adf458d9b..897b657d5d 100644 --- a/chef/spec/unit/cookbook_spec.rb +++ b/chef/spec/unit/cookbook_spec.rb @@ -6,9 +6,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,18 +21,18 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) describe Chef::CookbookVersion do # COOKBOOK_PATH = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks", "openldap")) before(:each) do - Chef::Config.cookbook_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_repo = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @cookbook = @cookbook_collection[:openldap] @node = Chef::Node.new @node.name "JuliaChild" @run_context = Chef::RunContext.new(@node, @cookbook_collection) end - + it "should have a name" do @cookbook.name.should == :openldap end - + it "should allow you to set the list of attribute files and create the mapping from short names to paths" do @cookbook.attribute_filenames = [ "attributes/one.rb", "attributes/two.rb" ] @cookbook.attribute_filenames.should == [ "attributes/one.rb", "attributes/two.rb" ] @@ -40,7 +40,7 @@ describe Chef::CookbookVersion do @cookbook.attribute_filenames_by_short_filename["one"].should == "attributes/one.rb" @cookbook.attribute_filenames_by_short_filename["two"].should == "attributes/two.rb" end - + it "should allow you to set the list of recipe files and create the mapping of recipe short name to filename" do @cookbook.recipe_filenames = [ "recipes/one.rb", "recipes/two.rb" ] @cookbook.recipe_filenames.should == [ "recipes/one.rb", "recipes/two.rb" ] @@ -55,30 +55,30 @@ describe Chef::CookbookVersion do @cookbook.fully_qualified_recipe_names.include?("openldap::two").should == true @cookbook.fully_qualified_recipe_names.include?("openldap::three").should == true end - + it "should find a preferred file" do pending end - + it "should not return an unchanged preferred file" do pending @cookbook.preferred_filename(@node, :files, 'a-filename', 'the-checksum').should be_nil end - + # TODO: timh, cw: 5/20/2010: removed CookbookVersion.recipe? as it's not used; see cookbook.rb # it "should allow you to test for a recipe with recipe?" do # @cookbook.recipe_filenames = [ "one", "two" ] # @cookbook.recipe?("one").should eql(true) # @cookbook.recipe?("shanghai").should eql(false) # end - + # TODO: timh, cw: 5/20/2010: removed CookbookVersion.recipe? as it's not used; see cookbook.rb # it "should allow you to test for a recipe? with a fq recipe name" do # @cookbook.recipe_filenames = [ "one", "two" ] # @cookbook.recipe?("openldap::one").should eql(true) # @cookbook.recipe?("shanghai::city").should eql(false) # end - + it "should allow you to include a fully-qualified recipe using the DSL" do # DSL method include_recipe allows multiple arguments, so extract the first recipe = @run_context.include_recipe("openldap::gigantor").first @@ -87,7 +87,7 @@ describe Chef::CookbookVersion do recipe.cookbook_name.should == :openldap @run_context.resource_collection[0].name.should == "blanket" end - + it "should raise an ArgumentException if you try to load a bad recipe name" do lambda { @cookbook.load_recipe("doesnt_exist", @node) }.should raise_error(ArgumentError) end @@ -96,5 +96,5 @@ describe Chef::CookbookVersion do @node.include_attribute("openldap::smokey") @node.smokey.should == "robinson" end - + end diff --git a/chef/spec/unit/mixin/template_spec.rb b/chef/spec/unit/mixin/template_spec.rb index 277db0e043..5b61d43c43 100644 --- a/chef/spec/unit/mixin/template_spec.rb +++ b/chef/spec/unit/mixin/template_spec.rb @@ -6,9 +6,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,7 +21,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_hel class TinyTemplateClass; include Chef::Mixin::Template; end require 'cgi' describe Chef::Mixin::Template, "render_template" do - + before :each do @template = TinyTemplateClass.new end @@ -31,29 +31,29 @@ describe Chef::Mixin::Template, "render_template" do tmp.open.read.should == "bar" end end - + it "should provide a node method to access @node" do @template.render_template("<%= node %>",{:node => "tehShizzle"}) do |tmp| tmp.open.read.should == "tehShizzle" end end - + it "should yield the tempfile it renders the template to" do @template.render_template("abcdef", {}) do |tempfile| tempfile.should be_kind_of(Tempfile) end end - + describe "when an exception is raised in the template" do def do_raise @context = {:chef => "cool"} @template.render_template("foo\nbar\nbaz\n<%= this_is_not_defined %>\nquin\nqunx\ndunno", @context) {|r| r} end - + it "should catch and re-raise the exception as a TemplateError" do lambda { do_raise }.should raise_error(Chef::Mixin::Template::TemplateError) end - + it "should raise an error if an attempt is made to access node but it is nil" do lambda {@template.render_template("<%= node %>",{}) {|r| r}}.should raise_error(Chef::Mixin::Template::TemplateError) end @@ -66,32 +66,32 @@ describe Chef::Mixin::Template, "render_template" do @exception = e end end - + it "should have the original exception" do @exception.original_exception.should be @exception.original_exception.message.should =~ /undefined local variable or method `this_is_not_defined'/ end - + it "should determine the line number of the exception" do @exception.line_number.should == 4 end - + it "should provide a source listing of the template around the exception" do @exception.source_listing.should == " 2: bar\n 3: baz\n 4: <%= this_is_not_defined %>\n 5: quin\n 6: qunx" end - + it "should provide the evaluation context of the template" do @exception.context.should == @context end - + it "should defer the message to the original exception" do @exception.message.should =~ /undefined local variable or method `this_is_not_defined'/ end - + it "should provide a nice source location" do @exception.source_location.should == "on line #4" end - + it "should create a pretty output for the terminal" do @exception.to_s.should =~ /Chef::Mixin::Template::TemplateError/ @exception.to_s.should =~ /undefined local variable or method `this_is_not_defined'/ diff --git a/chef/spec/unit/node_spec.rb b/chef/spec/unit/node_spec.rb index 2ef0b17199..0e83e38ad7 100644 --- a/chef/spec/unit/node_spec.rb +++ b/chef/spec/unit/node_spec.rb @@ -123,8 +123,8 @@ describe Chef::Node do describe "attributes" do it "should be loaded from the node's cookbooks" do - Chef::Config.cookbook_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) - @node.cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_repo = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) + @node.cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @node.load_attributes @node.ldap_server.should eql("ops1prod") @node.ldap_basedn.should eql("dc=hjksolutions,dc=com") diff --git a/chef/spec/unit/provider/cookbook_file_spec.rb b/chef/spec/unit/provider/cookbook_file_spec.rb index a4ced07fba..4836c6a592 100644 --- a/chef/spec/unit/provider/cookbook_file_spec.rb +++ b/chef/spec/unit/provider/cookbook_file_spec.rb @@ -21,11 +21,11 @@ require 'ostruct' describe Chef::Provider::CookbookFile do before do - Chef::Config.cookbook_path(File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } + @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } @node = Chef::Node.new - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @run_context = Chef::RunContext.new(@node, @cookbook_collection) @new_resource = Chef::Resource::CookbookFile.new('apache2_module_conf_generate.pl') @@ -49,13 +49,13 @@ EXPECTED end describe "when loading the current file state" do - + it "converts windows-y filenames to unix-y ones" do @new_resource.path('\windows\stuff') @provider.load_current_resource @new_resource.path.should == '/windows/stuff' end - + it "sets the current resources path to the same as the new resource" do @new_resource.path('/tmp/file') @provider.load_current_resource @@ -116,7 +116,7 @@ EXPECTED end actual.should == @file_content end - + it "installs the file from the cookbook cache" do @new_resource.path(@install_to) @provider.should_receive(:backup_new_resource) @@ -125,7 +125,7 @@ EXPECTED actual = IO.read(@install_to) actual.should == @file_content end - + it "installs the file for create_if_missing" do @new_resource.path(@install_to) @provider.should_receive(:set_all_access_controls) @@ -155,7 +155,7 @@ EXPECTED @current_resource = @new_resource.dup @provider.current_resource = @current_resource end - + it "overwrites it when the create action is called" do @provider.should_receive(:set_all_access_controls) @provider.should_receive(:backup_new_resource) @@ -187,7 +187,7 @@ EXPECTED after { @tempfile && @tempfile.close! } end - + describe "when the file has the correct content" do before do @tempfile = Tempfile.open('cookbook_file_spec') diff --git a/chef/spec/unit/provider/package_spec.rb b/chef/spec/unit/provider/package_spec.rb index 52f88d1058..bb79e6b40b 100644 --- a/chef/spec/unit/provider/package_spec.rb +++ b/chef/spec/unit/provider/package_spec.rb @@ -6,9 +6,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,68 +26,68 @@ describe Chef::Provider::Package do @current_resource = Chef::Resource::Package.new('emacs') @provider = Chef::Provider::Package.new(@new_resource, @run_context) @provider.current_resource = @current_resource - + @provider.candidate_version = "1.0" end - + describe "when installing a package" do before(:each) do @provider.current_resource = @current_resource @provider.stub!(:install_package).and_return(true) end - + it "should raise a Chef::Exceptions::Package if no version is specified, and no candidate is available" do @provider.candidate_version = nil lambda { @provider.action_install }.should raise_error(Chef::Exceptions::Package) end - + it "should call preseed_package if a response_file is given" do @new_resource.stub!(:response_file).and_return("foo") @provider.should_receive(:preseed_package).with( - @new_resource.name, + @new_resource.name, @provider.candidate_version ).and_return(true) @provider.action_install end - + it "should not call preseed_package if a response_file is not given" do @provider.should_not_receive(:preseed_package) @provider.action_install end - + it "should install the package at the candidate_version if it is not already installed" do @provider.should_receive(:install_package).with( - @new_resource.name, + @new_resource.name, @provider.candidate_version ).and_return(true) @provider.action_install - end - + end + it "should install the package at the version specified if it is not already installed" do @new_resource.stub!(:version).and_return("1.0") @provider.should_receive(:install_package).with( - @new_resource.name, + @new_resource.name, @new_resource.version ).and_return(true) @provider.action_install end - + it "should install the package at the version specified if a different version is installed" do @new_resource.stub!(:version).and_return("1.0") @current_resource.stub!(:version).and_return("0.99") @provider.should_receive(:install_package).with( - @new_resource.name, + @new_resource.name, @new_resource.version ).and_return(true) @provider.action_install end - + it "should not install the package if it is already installed and no version is specified" do @current_resource.stub!(:version).and_return("1.0") @provider.should_not_receive(:install_package) @provider.action_install - end - + end + it "should not install the package if it is already installed at the version specified" do @current_resource.stub!(:version).and_return("1.0") @new_resource.stub!(:version).and_return("1.0") @@ -98,7 +98,7 @@ describe Chef::Provider::Package do it "should call the candidate_version accessor if the package is not currently installed" do @provider.should_receive(:candidate_version).and_return(true) @provider.action_install - end + end it "should not call the candidate_version accessor if the package is already installed and no version is specified" do @current_resource.stub!(:version).and_return("1.0") @@ -125,12 +125,12 @@ describe Chef::Provider::Package do @provider.should_not_receive(:candidate_version) @provider.action_install end - + it "should set the resource to updated if it installs the package" do @provider.action_install @new_resource.should be_updated end - + end describe "when upgrading the package" do @@ -140,23 +140,23 @@ describe Chef::Provider::Package do it "should upgrade the package if the current version is not the candidate version" do @provider.should_receive(:upgrade_package).with( - @new_resource.name, + @new_resource.name, @provider.candidate_version ).and_return(true) @provider.action_upgrade end - + it "should set the resource to updated if it installs the package" do @provider.action_upgrade @new_resource.should be_updated end - + it "should not install the package if the current version is the candidate version" do @current_resource.version "1.0" @provider.should_not_receive(:upgrade_package) @provider.action_upgrade end - + it "should print the word 'uninstalled' if there was no original version" do @current_resource.stub!(:version).and_return(nil) Chef::Log.should_receive(:info).with("Upgrading #{@new_resource} version from uninstalled to 1.0") @@ -248,19 +248,19 @@ describe Chef::Provider::Package do describe "when running commands to be implemented by subclasses" do it "should raises UnsupportedAction for install" do - lambda { @provider.install_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) + lambda { @provider.install_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) end it "should raises UnsupportedAction for upgrade" do - lambda { @provider.upgrade_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) + lambda { @provider.upgrade_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) end it "should raises UnsupportedAction for remove" do - lambda { @provider.remove_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) + lambda { @provider.remove_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) end it "should raises UnsupportedAction for purge" do - lambda { @provider.purge_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) + lambda { @provider.purge_package('emacs', '1.4.2') }.should raise_error(Chef::Exceptions::UnsupportedAction) end it "should raise UnsupportedAction for preseed_package" do @@ -271,11 +271,11 @@ describe Chef::Provider::Package do describe "when given a response file" do before(:each) do - Chef::Config.cookbook_path(File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } + @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } @node = Chef::Node.new - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @run_context = Chef::RunContext.new(@node, @cookbook_collection) @node[:platform] = 'PLATFORM: just testing' diff --git a/chef/spec/unit/provider/remote_directory_spec.rb b/chef/spec/unit/provider/remote_directory_spec.rb index 089b24a4dc..896f3be864 100644 --- a/chef/spec/unit/provider/remote_directory_spec.rb +++ b/chef/spec/unit/provider/remote_directory_spec.rb @@ -6,9 +6,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,17 +26,17 @@ describe Chef::Provider::RemoteDirectory do @resource.source "remotedir" @resource.cookbook('openldap') - Chef::Config.cookbook_path(File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } + @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } @node = Chef::Node.new - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @run_context = Chef::RunContext.new(@node, @cookbook_collection) @provider = Chef::Provider::RemoteDirectory.new(@resource, @run_context) @provider.current_resource = @resource.clone end - + describe "when access control is configured on the resource" do before do @resource.mode "0750" @@ -62,7 +62,7 @@ describe Chef::Provider::RemoteDirectory do it "configures access control on files in the directory" do @resource.cookbook "berlin_style_tasty_cupcakes" - cookbook_file = @provider.send(:cookbook_file_resource, + cookbook_file = @provider.send(:cookbook_file_resource, "/target/destination/path.txt", "relative/source/path.txt") cookbook_file.cookbook_name.should == "berlin_style_tasty_cupcakes" @@ -78,7 +78,7 @@ describe Chef::Provider::RemoteDirectory do before do @node[:platform] = :just_testing @node[:platform_version] = :just_testing - + @destination_dir = Dir.tmpdir + '/remote_directory_test' @resource.path(@destination_dir) end @@ -94,7 +94,7 @@ describe Chef::Provider::RemoteDirectory do File.exist?(@destination_dir + '/remotesubdir/.a_dotfile').should be_true File.exist?(@destination_dir + '/.a_dotdir/.a_dotfile_in_a_dotdir').should be_true end - + describe "with purging enabled" do before {@resource.purge(true)} diff --git a/chef/spec/unit/provider/template_spec.rb b/chef/spec/unit/provider/template_spec.rb index 5b85642e72..b8b55f69a2 100644 --- a/chef/spec/unit/provider/template_spec.rb +++ b/chef/spec/unit/provider/template_spec.rb @@ -20,18 +20,18 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_hel describe Chef::Provider::Template do before(:each) do - Chef::Config.cookbook_path(File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))) - Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } + @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks")) + Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) } @node = Chef::Node.new - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @run_context = Chef::RunContext.new(@node, @cookbook_collection) - + @rendered_file_location = Dir.tmpdir + '/openldap_stuff.conf' - + @resource = Chef::Resource::Template.new(@rendered_file_location) @resource.cookbook_name = 'openldap' - + @provider = Chef::Provider::Template.new(@resource, @run_context) @current_resource = @resource.dup @provider.current_resource = @current_resource @@ -46,7 +46,7 @@ describe Chef::Provider::Template do it "finds the template file in the coobook cache if it isn't local" do @provider.template_location.should == CHEF_SPEC_DATA + '/cookbooks/openldap/templates/default/openldap_stuff.conf.erb' end - + it "finds the template file locally if it is local" do @resource.local(true) @resource.source('/tmp/its_on_disk.erb') @@ -88,14 +88,14 @@ describe Chef::Provider::Template do before do File.open(@rendered_file_location, "w+") { |f| f.print "blargh" } end - + it "overwrites the file with the updated content when the create action is run" do @node[:slappiness] = "a warm gun" @provider.should_receive(:backup) @provider.action_create IO.read(@rendered_file_location).should == "slappiness is a warm gun" end - + it "should set the file access control as specified in the resource" do @resource.owner("adam") @resource.group("wheel") @@ -118,7 +118,7 @@ describe Chef::Provider::Template do File.open(@rendered_file_location, "w") { |f| f.print "slappiness is a warm gun" } @current_resource.checksum('4ff94a87794ed9aefe88e734df5a66fc8727a179e9496cbd88e3b5ec762a5ee9') end - + it "does not backup the original or overwrite it" do @node[:slappiness] = "a warm gun" @provider.should_not_receive(:backup) diff --git a/chef/spec/unit/provider_spec.rb b/chef/spec/unit/provider_spec.rb index 4d86b8371b..9f6a510770 100644 --- a/chef/spec/unit/provider_spec.rb +++ b/chef/spec/unit/provider_spec.rb @@ -6,9 +6,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,8 +20,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) describe Chef::Provider do before(:each) do - Chef::Config.cookbook_path = [] - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_collection = Chef::CookbookCollection.new([]) @node = Chef::Node.new @node.name "latte" @run_context = Chef::RunContext.new(@node, @cookbook_collection) @@ -29,23 +28,23 @@ describe Chef::Provider do @resource.cookbook_name = "a_delicious_pie" @provider = Chef::Provider.new(@resource, @run_context) end - + it "should store the resource passed to new as new_resource" do @provider.new_resource.should eql(@resource) end - + it "should store the node passed to new as node" do @provider.node.should eql(@node) end - + it "should have nil for current_resource by default" do @provider.current_resource.should eql(nil) - end - + end + it "should return true for action_nothing" do @provider.action_nothing.should eql(true) end - + it "evals embedded recipes with a pristine resource collection" do @provider.run_context.instance_variable_set(:@resource_collection, "doesn't matter what this is") temporary_collection = nil diff --git a/chef/spec/unit/recipe_spec.rb b/chef/spec/unit/recipe_spec.rb index 66945658bc..0f5bfa5a7d 100644 --- a/chef/spec/unit/recipe_spec.rb +++ b/chef/spec/unit/recipe_spec.rb @@ -8,9 +8,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,8 +22,8 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper")) describe Chef::Recipe do before(:each) do - Chef::Config.cookbook_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_repo = File.expand_path(File.join(File.dirname(__FILE__), "..", "data", "cookbooks")) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo)) @node = Chef::Node.new @node[:tags] = Array.new @run_context = Chef::RunContext.new(@node, @cookbook_collection) @@ -34,7 +34,7 @@ describe Chef::Recipe do # we're running tests. @recipe.stub!(:pp) end - + describe "method_missing" do describe "resources" do it "should load a two word (zen_master) resource" do @@ -44,7 +44,7 @@ describe Chef::Recipe do end end.should_not raise_error(ArgumentError) end - + it "should load a one word (cat) resource" do lambda do @recipe.cat "loulou" do @@ -52,15 +52,15 @@ describe Chef::Recipe do end end.should_not raise_error(ArgumentError) end - - it "should load a four word (one_two_three_four) resource" do + + it "should load a four word (one_two_three_four) resource" do lambda do @recipe.one_two_three_four "numbers" do i_can_count true end end.should_not raise_error(ArgumentError) end - + it "should throw an error if you access a resource that we can't find" do lambda { @recipe.not_home("not_home_resource") }.should raise_error(NameError) end @@ -70,30 +70,30 @@ describe Chef::Recipe do @recipe.cat }.should raise_error(ArgumentError, "You must supply a name when declaring a cat resource") end - + it "should allow regular errors (not NameErrors) to pass unchanged" do lambda { - @recipe.cat("felix") { raise ArgumentError, "You Suck" } + @recipe.cat("felix") { raise ArgumentError, "You Suck" } }.should raise_error(ArgumentError) end - + it "should add our zen_master to the collection" do @recipe.zen_master "monkey" do peace true end @run_context.resource_collection.lookup("zen_master[monkey]").name.should eql("monkey") end - + it "should add our zen masters to the collection in the order they appear" do %w{monkey dog cat}.each do |name| @recipe.zen_master name do peace true end end - + @run_context.resource_collection.map{|r| r.name}.should eql(["monkey", "dog", "cat"]) end - + it "should return the new resource after creating it" do res = @recipe.zen_master "makoto" do peace true @@ -102,7 +102,7 @@ describe Chef::Recipe do res.name.should eql("makoto") end end - + describe "resource definitions" do it "should execute defined resources" do crow_define = Chef::ResourceDefinition.new @@ -138,7 +138,7 @@ describe Chef::Recipe do end end - + describe "instance_eval" do it "should handle an instance_eval properly" do code = <<-CODE @@ -150,7 +150,7 @@ describe Chef::Recipe do @recipe.resources(:zen_master => "gnome").name.should eql("gnome") end end - + describe "from_file" do it "should load a resource from a ruby file" do @recipe.from_file(File.join(CHEF_SPEC_DATA, "recipes", "test.rb")) @@ -161,12 +161,12 @@ describe Chef::Recipe do res.group.should eql("root") res.mode.should eql(0644) end - + it "should raise an exception if the file cannot be found or read" do lambda { @recipe.from_file("/tmp/monkeydiving") }.should raise_error(IOError) end end - + describe "include_recipe" do it "should evaluate another recipe with include_recipe" do @run_context.include_recipe "openldap::gigantor" @@ -174,19 +174,19 @@ describe Chef::Recipe do res.name.should eql("blanket") res.pretty_kitty.should eql(false) end - + it "should load the default recipe for a cookbook if include_recipe is called without a ::" do @run_context.include_recipe "openldap" res = @run_context.resource_collection.resources(:cat => "blanket") res.name.should eql("blanket") res.pretty_kitty.should eql(true) end - + it "should store that it has seen a recipe in node.run_state[:seen_recipes]" do @run_context.include_recipe "openldap" @node.run_state[:seen_recipes].should have_key("openldap") end - + it "should not include the same recipe twice" do @cookbook_collection[:openldap].should_receive(:load_recipe).with("default", @run_context) @recipe.include_recipe "openldap" @@ -200,43 +200,43 @@ describe Chef::Recipe do @recipe.tag "foo" @node[:tags].should include("foo") end - + it "should set multiple tags via tag" do @recipe.tag "foo", "bar" @node[:tags].should include("foo") @node[:tags].should include("bar") end - + it "should not set the same tag twice via tag" do @recipe.tag "foo" @recipe.tag "foo" @node[:tags].should eql([ "foo" ]) end - + it "should return the current list of tags from tag with no arguments" do @recipe.tag "foo" @recipe.tag.should eql([ "foo" ]) end - + it "should return true from tagged? if node is tagged" do @recipe.tag "foo" @recipe.tagged?("foo").should be(true) end - + it "should return false from tagged? if node is not tagged" do @recipe.tagged?("foo").should be(false) end - + it "should return false from tagged? if node is not tagged" do @recipe.tagged?("foo").should be(false) end - + it "should remove a tag from the tag list via untag" do @recipe.tag "foo" @recipe.untag "foo" @node[:tags].should eql([]) end - + it "should remove multiple tags from the tag list via untag" do @recipe.tag "foo", "bar" @recipe.untag "bar", "foo" diff --git a/chef/spec/unit/resource_spec.rb b/chef/spec/unit/resource_spec.rb index 06f3b36a8c..00496d7d71 100644 --- a/chef/spec/unit/resource_spec.rb +++ b/chef/spec/unit/resource_spec.rb @@ -8,9 +8,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -26,13 +26,13 @@ end describe Chef::Resource do before(:each) do - Chef::Config[:cookbook_path] = File.join(CHEF_SPEC_DATA, 'cookbooks') - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @cookbook_repo_path = File.join(CHEF_SPEC_DATA, 'cookbooks') + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@cookbook_repo_path)) @node = Chef::Node.new @run_context = Chef::RunContext.new(@node, @cookbook_collection) @resource = Chef::Resource.new("funk", @run_context) end - + describe "load_prior_resource" do before(:each) do @prior_resource = Chef::Resource.new("funk") @@ -43,12 +43,12 @@ describe Chef::Resource do @resource.allowed_actions << :funkytown @run_context.resource_collection << @prior_resource end - + it "should load the attributes of a prior resource" do @resource.load_prior_resource @resource.supports.should == { :funky => true } end - + it "should not inherit the action from the prior resource" do @resource.load_prior_resource @resource.action.should_not == @prior_resource.action @@ -59,21 +59,21 @@ describe Chef::Resource do it "should have a name" do @resource.name.should eql("funk") end - + it "should let you set a new name" do @resource.name "monkey" @resource.name.should eql("monkey") end - + it "should not be valid without a name" do lambda { @resource.name false }.should raise_error(ArgumentError) end - + it "should always have a string for name" do lambda { @resource.name Hash.new }.should raise_error(ArgumentError) end end - + describe "noop" do it "should accept true or false for noop" do lambda { @resource.noop true }.should_not raise_error(ArgumentError) @@ -81,32 +81,32 @@ describe Chef::Resource do lambda { @resource.noop "eat it" }.should raise_error(ArgumentError) end end - + describe "notifies" do it "should make notified resources appear in the actions hash" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee") @resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}.should_not be_nil end - + it "should make notified resources be capable of acting immediately" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee"), :immediate @resource.immediate_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}.should_not be_nil end - + it "should raise an exception if told to act in other than :delay or :immediate(ly)" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") - lambda { + lambda { @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee"), :someday }.should raise_error(ArgumentError) end - + it "should allow multiple notified resources appear in the actions hash" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "coffee") @resource.delayed_notifications.detect{|e| e.resource.name == "coffee" && e.action == :reload}.should_not be_nil - + @run_context.resource_collection << Chef::Resource::ZenMaster.new("beans") @resource.notifies :reload, @run_context.resource_collection.find(:zen_master => "beans") @resource.delayed_notifications.detect{|e| e.resource.name == "beans" && e.action == :reload}.should_not be_nil @@ -130,27 +130,27 @@ describe Chef::Resource do @resource.delayed_notifications.should include(expected_notification) end end - - describe "subscribes" do + + describe "subscribes" do it "should make resources appear in the actions hash of subscribed nodes" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") zr = @run_context.resource_collection.find(:zen_master => "coffee") @resource.subscribes :reload, zr zr.delayed_notifications.detect{|e| e.resource.name == "funk" && e.action == :reload}.should_not be_nil end - + it "should make resources appear in the actions hash of subscribed nodes" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") zr = @run_context.resource_collection.find(:zen_master => "coffee") @resource.subscribes :reload, zr zr.delayed_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}.should_not be_nil - + @run_context.resource_collection << Chef::Resource::ZenMaster.new("bean") zrb = @run_context.resource_collection.find(:zen_master => "bean") zrb.subscribes :reload, zr zr.delayed_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}.should_not be_nil end - + it "should make subscribed resources be capable of acting immediately" do @run_context.resource_collection << Chef::Resource::ZenMaster.new("coffee") zr = @run_context.resource_collection.find(:zen_master => "coffee") @@ -158,20 +158,20 @@ describe Chef::Resource do zr.immediate_notifications.detect{|e| e.resource.name == @resource.name && e.action == :reload}.should_not be_nil end end - - describe "to_s" do + + describe "to_s" do it "should become a string like resource_name[name]" do zm = Chef::Resource::ZenMaster.new("coffee") zm.to_s.should eql("zen_master[coffee]") end end - + describe "is" do it "should return the arguments passed with 'is'" do zm = Chef::Resource::ZenMaster.new("coffee") zm.is("one", "two", "three").should == %w|one two three| end - + it "should allow arguments preceeded by is to methods" do @resource.noop(@resource.is(true)) @resource.noop.should eql(true) @@ -185,12 +185,12 @@ describe Chef::Resource do json.should =~ /instance_vars/ end end - + describe "to_hash" do it "should convert to a hash" do hash = @resource.to_hash - expected_keys = [ :only_if, :allowed_actions, :params, :provider, - :updated, :updated_by_last_action, :before, :not_if, :supports, + expected_keys = [ :only_if, :allowed_actions, :params, :provider, + :updated, :updated_by_last_action, :before, :not_if, :supports, :delayed_notifications, :immediate_notifications, :noop, :ignore_failure, :name, :source_line, :action, :not_if_args, :only_if_args @@ -200,7 +200,7 @@ describe Chef::Resource do hash[:name].should eql("funk") end end - + describe "self.json_create" do it "should deserialize itself from json" do json = @resource.to_json @@ -209,45 +209,45 @@ describe Chef::Resource do serialized_node.name.should eql(@resource.name) end end - + describe "supports" do it "should allow you to set what features this resource supports" do support_hash = { :one => :two } @resource.supports(support_hash) @resource.supports.should eql(support_hash) end - + it "should return the current value of supports" do @resource.supports.should == {} end end - - describe "ignore_failure" do + + describe "ignore_failure" do it "should default to throwing an error if a provider fails for a resource" do @resource.ignore_failure.should == false end - + it "should allow you to set whether a provider should throw exceptions with ignore_failure" do @resource.ignore_failure(true) @resource.ignore_failure.should == true end - + it "should allow you to epic_fail" do @resource.epic_fail(true) @resource.epic_fail.should == true end end - + describe "setting the base provider class for the resource" do - + it "defaults to Chef::Provider for the base class" do Chef::Resource.provider_base.should == Chef::Provider end - + it "allows the base provider to be overriden by a " do ResourceTestHarness.provider_base.should == Chef::Provider::Package end - + end it "supports accessing the node via the @node instance variable [DEPRECATED]" do diff --git a/chef/spec/unit/run_context_spec.rb b/chef/spec/unit/run_context_spec.rb index d8616052f0..c38f3fd3b8 100644 --- a/chef/spec/unit/run_context_spec.rb +++ b/chef/spec/unit/run_context_spec.rb @@ -25,8 +25,8 @@ Chef::Log.level = :debug describe Chef::RunContext do before(:each) do Chef::Config.node_path(File.expand_path(File.join(CHEF_SPEC_DATA, "run_context", "nodes"))) - Chef::Config.cookbook_path(File.expand_path(File.join(CHEF_SPEC_DATA, "run_context", "cookbooks"))) - @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new) + @chef_repo_path = File.expand_path(File.join(CHEF_SPEC_DATA, "run_context", "cookbooks")) + @cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(@chef_repo_path)) @node = Chef::Node.new @node.find_file("run_context") @run_context = Chef::RunContext.new(@node, @cookbook_collection) diff --git a/features/steps/cookbook_steps.rb b/features/steps/cookbook_steps.rb index 7675bd416b..cae8f07b6c 100644 --- a/features/steps/cookbook_steps.rb +++ b/features/steps/cookbook_steps.rb @@ -36,12 +36,10 @@ def compare_manifests(manifest1, manifest2) end Before do - save_cookbook_path = Chef::Config[:cookbook_path] FileUtils.mkdir "#{datadir}/cookbooks_not_uploaded_at_feature_start/testcookbook_invalid_empty" unless File.exist?("#{datadir}/cookbooks_not_uploaded_at_feature_start/testcookbook_invalid_empty") - Chef::Config[:cookbook_path] = File.join(datadir, "cookbooks_not_uploaded_at_feature_start") - Chef::Cookbook::FileVendor.on_create {|manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest) } - @cookbook_loader_not_uploaded_at_feature_start = Chef::CookbookLoader.new - Chef::Config[:cookbook_path] = save_cookbook_path + extra_cookbook_repo = File.join(datadir, "cookbooks_not_uploaded_at_feature_start") + Chef::Cookbook::FileVendor.on_create {|manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, extra_cookbook_repo) } + @cookbook_loader_not_uploaded_at_feature_start = Chef::CookbookLoader.new(extra_cookbook_repo) end Given /^a local cookbook repository$/ do |