summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan McLellan <btm@opscode.com>2012-10-30 13:44:23 -0700
committerBryan McLellan <btm@opscode.com>2012-10-30 13:44:23 -0700
commit40bb09b6605852b362875ec99438f22af6c35676 (patch)
tree932e28c75bcccc5a18a86d1371612b0fcdd9429c
parent7c757e2281e862a26c22795ffd957e6048da02b1 (diff)
parent6668c614b3762ded59595241f4719dbec98eaa1f (diff)
downloadchef-40bb09b6605852b362875ec99438f22af6c35676.tar.gz
Merge branch '10-stable'
Conflicts: chef-expander/lib/chef/expander/version.rb chef-server-api/lib/chef-server-api/version.rb chef-server-webui/lib/chef-server-webui/version.rb chef-server/lib/chef-server/version.rb chef-solr/lib/chef/solr/version.rb chef/lib/chef/node/attribute.rb lib/chef/node.rb
-rw-r--r--Gemfile6
-rw-r--r--chef/spec/functional/resource/cookbook_file_spec.rb51
-rw-r--r--lib/chef/application.rb15
-rw-r--r--lib/chef/application/client.rb12
-rw-r--r--lib/chef/application/solo.rb12
-rw-r--r--lib/chef/application/windows_service.rb11
-rw-r--r--lib/chef/config.rb3
-rw-r--r--lib/chef/knife/cookbook_site_install.rb11
-rw-r--r--lib/chef/provider/cookbook_file.rb3
-rw-r--r--lib/chef/provider/file.rb25
-rw-r--r--lib/chef/provider/remote_directory.rb39
-rw-r--r--lib/chef/resource_reporter.rb39
-rw-r--r--spec/unit/application/solo_spec.rb4
-rw-r--r--spec/unit/mixin/enforce_ownership_and_permissions_spec.rb2
-rw-r--r--spec/unit/provider/directory_spec.rb138
-rw-r--r--spec/unit/provider/file_spec.rb138
-rw-r--r--spec/unit/provider/remote_directory_spec.rb7
-rw-r--r--spec/unit/resource_reporter_spec.rb19
18 files changed, 324 insertions, 211 deletions
diff --git a/Gemfile b/Gemfile
index 40868b9677..a1d35569e1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -7,11 +7,7 @@ gem "ronn"
group(:development, :test) do
gem 'rack'
-
- # The 'ruby' platform is surprisingly just unix-y platforms
- # thin requires eventmachine, which won't work under Ruby 1.9 on Windows
- # http://gembundler.com/man/gemfile.5.html
- gem 'thin', :platforms => :ruby
+ gem 'thin'
# Eventmachine 1.0.0 is causing functional test failures on Solaris
# 9 SPARC. Pinning em to 0.12.10 solves this issue until we can
diff --git a/chef/spec/functional/resource/cookbook_file_spec.rb b/chef/spec/functional/resource/cookbook_file_spec.rb
new file mode 100644
index 0000000000..adc1f7eef8
--- /dev/null
+++ b/chef/spec/functional/resource/cookbook_file_spec.rb
@@ -0,0 +1,51 @@
+#
+# Author:: Tim Hinderliter (<tim@opscode.com>)
+# Copyright:: Copyright (c) 2012 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 'spec_helper'
+
+describe Chef::Resource::CookbookFile do
+ include_context Chef::Resource::File
+
+ let(:file_base) { 'cookbook_file_spec' }
+ let(:source) { 'java.response' }
+ let(:cookbook_name) { 'java' }
+ let(:expected_content) { IO.read(File.join(CHEF_SPEC_DATA, 'cookbooks', 'java', 'files', 'default', 'java.response')) }
+
+ def create_resource
+ # set up cookbook collection for this run to use, based on our
+ # spec data.
+ cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, 'cookbooks'))
+ Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
+ cookbook_collection = Chef::CookbookCollection.new(Chef::CookbookLoader.new(cookbook_repo))
+
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, cookbook_collection, events)
+ resource = Chef::Resource::CookbookFile.new(path, run_context)
+ resource.cookbook(cookbook_name)
+ resource.source(source)
+
+ resource
+ end
+
+ let!(:resource) do
+ create_resource
+ end
+
+ it_behaves_like "a file resource"
+end
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 328a81a2eb..f864996ea5 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -34,6 +34,8 @@ class Chef::Application
def initialize
super
+ @chef_client = nil
+ @chef_client_json = nil
trap("TERM") do
Chef::Application.fatal!("SIGTERM received, stopping", 1)
end
@@ -127,6 +129,18 @@ class Chef::Application
raise Chef::Exceptions::Application, "#{self.to_s}: you must override run_application"
end
+ # Initializes Chef::Client instance and runs it
+ def run_chef_client
+ @chef_client = Chef::Client.new(
+ @chef_client_json,
+ :override_runlist => config[:override_runlist]
+ )
+ @chef_client_json = nil
+
+ @chef_client.run
+ @chef_client = nil
+ end
+
private
def apply_config(config_file_path)
@@ -134,7 +148,6 @@ class Chef::Application
Chef::Config.merge!(config)
end
-
class << self
def debug_stacktrace(e)
message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 3a68a41c14..ef40a7a358 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -186,9 +186,6 @@ class Chef::Application::Client < Chef::Application
def initialize
super
-
- @chef_client = nil
- @chef_client_json = nil
end
# Reconfigure the chef client
@@ -274,14 +271,7 @@ class Chef::Application::Client < Chef::Application
Chef::Log.debug("Splay sleep #{splay} seconds")
sleep splay
end
- @chef_client = Chef::Client.new(
- @chef_client_json,
- :override_runlist => config[:override_runlist]
- )
- @chef_client_json = nil
-
- @chef_client.run
- @chef_client = nil
+ run_chef_client
if Chef::Config[:interval]
Chef::Log.debug("Sleeping for #{Chef::Config[:interval]} seconds")
unless SELF_PIPE.empty?
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index 7ec6c36e76..4aca7238f6 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -149,8 +149,6 @@ class Chef::Application::Solo < Chef::Application
def initialize
super
- @chef_solo = nil
- @chef_solo_json = nil
end
def reconfigure
@@ -182,7 +180,7 @@ class Chef::Application::Solo < Chef::Application
end
begin
- @chef_solo_json = Chef::JSONCompat.from_json(json_io.read)
+ @chef_client_json = Chef::JSONCompat.from_json(json_io.read)
json_io.close unless json_io.closed?
rescue JSON::ParserError => error
Chef::Application.fatal!("Could not parse the provided JSON file (#{Chef::Config[:json_attribs]})!: " + error.message, 2)
@@ -223,12 +221,7 @@ class Chef::Application::Solo < Chef::Application
sleep splay
end
- @chef_solo = Chef::Client.new(
- @chef_solo_json,
- :override_runlist => config[:override_runlist]
- )
- @chef_solo.run
- @chef_solo = nil
+ run_chef_client
if Chef::Config[:interval]
Chef::Log.debug("Sleeping for #{Chef::Config[:interval]} seconds")
sleep Chef::Config[:interval]
@@ -251,4 +244,5 @@ class Chef::Application::Solo < Chef::Application
end
end
end
+
end
diff --git a/lib/chef/application/windows_service.rb b/lib/chef/application/windows_service.rb
index 961ec8f92f..0d4a022fdf 100644
--- a/lib/chef/application/windows_service.rb
+++ b/lib/chef/application/windows_service.rb
@@ -88,14 +88,7 @@ class Chef
# If we've stopped, then bail out now, instead of going on to run Chef
next if state != RUNNING
- @chef_client = Chef::Client.new(
- @chef_client_json,
- :override_runlist => config[:override_runlist]
- )
- @chef_client_json = nil
-
- @chef_client.run
- @chef_client = nil
+ run_chef_client
Chef::Log.debug("Sleeping for #{Chef::Config[:interval]} seconds")
client_sleep Chef::Config[:interval]
@@ -225,7 +218,7 @@ class Chef
sleep chunk_length
end
end
-
+
end
end
end
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index 61c8806a66..dceac4fa34 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -287,6 +287,9 @@ class Chef
cache_type "BasicFile"
cache_options({ :path => platform_specific_path("/var/chef/cache/checksums"), :skip_expires => true })
+ # Set to false to silence Chef 11 deprecation warnings:
+ chef11_deprecation_warnings true
+
# Arbitrary knife configuration data
knife Hash.new
diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb
index b2e0d84751..584735d8ff 100644
--- a/lib/chef/knife/cookbook_site_install.rb
+++ b/lib/chef/knife/cookbook_site_install.rb
@@ -107,6 +107,7 @@ class Chef
end
end
+
unless config[:no_deps]
md = Chef::Cookbook::Metadata.new
md.from_file(File.join(@install_path, @cookbook_name, "metadata.rb"))
@@ -143,13 +144,21 @@ class Chef
def extract_cookbook(upstream_file, version)
ui.info("Uncompressing #{@cookbook_name} version #{version}.")
- shell_out!("tar zxvf #{Shellwords.escape upstream_file}", :cwd => @install_path)
+ shell_out!("tar zxvf #{convert_path upstream_file}", :cwd => @install_path)
end
def clear_existing_files(cookbook_path)
ui.info("Removing pre-existing version.")
FileUtils.rmtree(cookbook_path) if File.directory?(cookbook_path)
end
+
+ def convert_path(upstream_file)
+ if ENV['MSYSTEM'] == 'MINGW32'
+ return upstream_file.sub(/^([[:alpha:]]):/, '/\1')
+ else
+ return Shellwords.escape upstream_file
+ end
+ end
end
end
end
diff --git a/lib/chef/provider/cookbook_file.rb b/lib/chef/provider/cookbook_file.rb
index 431f3f2367..144afbddeb 100644
--- a/lib/chef/provider/cookbook_file.rb
+++ b/lib/chef/provider/cookbook_file.rb
@@ -44,9 +44,6 @@ class Chef
Chef::Log.debug("#{@new_resource} staging #{file_cache_location} to #{tempfile.path}")
tempfile.close
FileUtils.cp(file_cache_location, tempfile.path)
- # Since the @new_resource.path file will not be updated
- # at the time of converge, we must use the tempfile
- update_new_file_state(tempfile.path)
end
Chef::Log.info("#{@new_resource} created file #{@new_resource.path}")
end
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index 659afc6517..77f5217027 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -132,7 +132,9 @@ class Chef
@current_resource.path(@new_resource.path)
if !::File.directory?(@new_resource.path)
if ::File.exist?(@new_resource.path)
- @current_resource.checksum(checksum(@new_resource.path))
+ if @action != :create_if_missing
+ @current_resource.checksum(checksum(@new_resource.path))
+ end
end
end
load_current_resource_attrs
@@ -142,6 +144,13 @@ class Chef
end
def load_current_resource_attrs
+ if Chef::Platform.windows?
+ # TODO: To work around CHEF-3554, add support for Windows
+ # equivalent, or implicit resource reporting won't work for
+ # Windows.
+ return
+ end
+
if ::File.exist?(@new_resource.path)
stat = ::File.stat(@new_resource.path)
@current_resource.owner(stat.uid)
@@ -215,13 +224,21 @@ class Chef
# override the default with the tempfile, since the
# file at @new_resource.path will not be updated on converge
def update_new_file_state(path=@new_resource.path)
+ if !::File.directory?(path)
+ @new_resource.checksum(checksum(path))
+ end
+
+ if Chef::Platform.windows?
+ # TODO: To work around CHEF-3554, add support for Windows
+ # equivalent, or implicit resource reporting won't work for
+ # Windows.
+ return
+ end
+
stat = ::File.stat(path)
@new_resource.owner(stat.uid)
@new_resource.mode(stat.mode & 07777)
@new_resource.group(stat.gid)
- if !::File.directory?(path)
- @new_resource.checksum(checksum(path))
- end
end
def action_create
diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb
index 9ccd7ea056..dee383f763 100644
--- a/lib/chef/provider/remote_directory.rb
+++ b/lib/chef/provider/remote_directory.rb
@@ -34,23 +34,27 @@ class Chef
def action_create
super
-
- files_to_purge = Set.new(
- Dir.glob(::File.join(@new_resource.path, '**', '*'), ::File::FNM_DOTMATCH).select do |name|
- name !~ /(?:^|#{Regexp.escape(::File::SEPARATOR)})\.\.?$/
- end
- )
- files_to_transfer.each do |cookbook_file_relative_path|
- create_cookbook_file(cookbook_file_relative_path)
- # the file is removed from the purge list
- files_to_purge.delete(::File.join(@new_resource.path, cookbook_file_relative_path))
- # parent directories are also removed from the purge list
- directories=::File.dirname(::File.join(@new_resource.path, cookbook_file_relative_path)).split(::File::SEPARATOR)
- for i in 0..directories.length-1
- files_to_purge.delete(::File.join(directories[0..i]))
+ files_to_purge = Set.new(Dir.glob(::File.join(@new_resource.path, '**', '*'),
+ ::File::FNM_DOTMATCH).select do |name|
+ name !~ /(?:^|#{Regexp.escape(::File::SEPARATOR)})\.\.?$/
+ end)
+
+ converge_by("Create managed files in directory") do
+ files_to_transfer.each do |cookbook_file_relative_path|
+ create_cookbook_file(cookbook_file_relative_path)
+ # the file is removed from the purge list
+ files_to_purge.delete(::File.join(@new_resource.path, cookbook_file_relative_path))
+ # parent directories are also removed from the purge list
+ directories=::File.dirname(::File.join(@new_resource.path, cookbook_file_relative_path)).split(::File::SEPARATOR)
+ for i in 0..directories.length-1
+ files_to_purge.delete(::File.join(directories[0..i]))
+ end
end
end
- purge_unmanaged_files(files_to_purge)
+
+ converge_by("Purge unmanaged files from directory") do
+ purge_unmanaged_files(files_to_purge)
+ end
end
def action_create_if_missing
@@ -170,5 +174,10 @@ class Chef
end
end
+
+ def whyrun_supported?
+ true
+ end
+
end
end
diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb
index 3d10c1e961..f9ad5e1cb9 100644
--- a/lib/chef/resource_reporter.rb
+++ b/lib/chef/resource_reporter.rb
@@ -116,15 +116,15 @@ class Chef
Chef::Log.info("Chef server generated run history id: #{@run_id}")
@summary_only = server_response["summary_only"]
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
- if !e.response || e.response.code.to_s != 404
+ if !e.response || e.response.code.to_s != "404"
if Chef::Config[:enable_reporting_url_fatals]
- Chef::Log.error("Received exception attempting to generate run history id (URL Path: #{resource_history_url}), and enable_reporting_url_fatals is set, aborting run.")
+ Chef::Log.error("Received exception #{"(" + e.response.code + ") " if e.response.code}attempting to generate run history id (URL Path: #{resource_history_url}), and enable_reporting_url_fatals is set, aborting run.")
raise
else
- Chef::Log.info("Received exception attempting to generate run history id (URL Path: #{resource_history_url}), disabling reporting for this run.")
+ Chef::Log.info("Received exception #{"(" + e.response.code + ") " if e.response.code}attempting to generate run history id (URL Path: #{resource_history_url}), disabling reporting for this run.")
end
else
- Chef::Log.debug("Received 404 attempting to generate run history id (URL Path: #{resource_history_url}), assuming feature is not supported.")
+ Chef::Log.debug("Received 404 attempting to generate run history id (URL Path: #{resource_history_url}), assuming feature is not supported on server.")
end
@reporting_enabled = false
end
@@ -187,17 +187,26 @@ class Chef
Chef::Log.info("Sending resource update report (run-id: #{@run_id})")
Chef::Log.debug run_data.inspect
compressed_data = encode_gzip(run_data.to_json)
- #if summary only is enabled send the uncompressed run_data excluding the run_data["resources"] and some additional metrics.
- if @summary_only
- run_data = report_summary(run_data, compressed_data)
- Chef::Log.info("run_data_summary: #{run_data}")
- @rest_client.post_rest(resource_history_url, run_data)
- else
- Chef::Log.debug("Sending Compressed Run Data...")
- # Since we're posting compressed data we can not directly call
- # post_rest which expects JSON
- reporting_url = @rest_client.create_url(resource_history_url)
- @rest_client.raw_http_request(:POST, reporting_url, {'Content-Encoding' => 'gzip'}, compressed_data)
+ begin
+ #if summary only is enabled send the uncompressed run_data excluding the run_data["resources"] and some additional metrics.
+ if @summary_only
+ run_data = report_summary(run_data, compressed_data)
+ Chef::Log.info("run_data_summary: #{run_data}")
+ @rest_client.post_rest(resource_history_url, run_data)
+ else
+ Chef::Log.debug("Sending compressed run data...")
+ # Since we're posting compressed data we can not directly call
+ # post_rest which expects JSON
+ reporting_url = @rest_client.create_url(resource_history_url)
+ @rest_client.raw_http_request(:POST, reporting_url, {'Content-Encoding' => 'gzip'}, compressed_data)
+ end
+ rescue Net::HTTPServerException => e
+ if e.response.code.to_s == "400"
+ Chef::FileCache.store("failed-reporting-data.json", Chef::JSONCompat.to_json_pretty(run_data), 0640)
+ Chef::Log.error("Failed to post reporting data to server (HTTP 400), saving to #{Chef::FileCache.load("failed-reporting-data.json", false)}")
+ else
+ Chef::Log.error("Failed to post reporting data to server (HTTP #{e.response.code.to_s})")
+ end
end
else
Chef::Log.debug("Server doesn't support resource history, skipping resource report.")
diff --git a/spec/unit/application/solo_spec.rb b/spec/unit/application/solo_spec.rb
index 148fb3cf87..96c89a37a6 100644
--- a/spec/unit/application/solo_spec.rb
+++ b/spec/unit/application/solo_spec.rb
@@ -71,7 +71,7 @@ describe Chef::Application::Solo do
it "should perform a RESTful GET on the supplied URL" do
@app.reconfigure
- @app.chef_solo_json.should == {"a" => "b"}
+ @app.instance_variable_get(:@chef_client_json).should == {"a" => "b"}
end
end
@@ -84,7 +84,7 @@ describe Chef::Application::Solo do
it "should parse the json out of the file" do
@app.reconfigure
- @app.chef_solo_json.should == {"a" => "b"}
+ @app.instance_variable_get(:@chef_client_json).should == {"a" => "b"}
end
end
diff --git a/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb b/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb
index 53a8260cdc..efbbe9218e 100644
--- a/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb
+++ b/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb
@@ -84,6 +84,8 @@ describe Chef::Mixin::EnforceOwnershipAndPermissions do
end
it "sets updated_by_last_action on the new resource" do
+ @provider.new_resource.owner(0) # CHEF-3557 hack - Set these because we don't for windows
+ @provider.new_resource.group(0) # CHEF-3557 hack - Set these because we don't for windows
@provider.new_resource.should_receive(:updated_by_last_action)
Chef::FileAccessControl.any_instance.stub(:set_all)
@provider.run_action(:create)
diff --git a/spec/unit/provider/directory_spec.rb b/spec/unit/provider/directory_spec.rb
index 4f297e0115..5118d086fc 100644
--- a/spec/unit/provider/directory_spec.rb
+++ b/spec/unit/provider/directory_spec.rb
@@ -33,74 +33,80 @@ describe Chef::Provider::Directory do
@directory = Chef::Provider::Directory.new(@new_resource, @run_context)
end
- it "should load the current resource based on the new resource" do
- File.stub!(:exist?).and_return(true)
- cstats = mock("stats")
- cstats.stub!(:uid).and_return(500)
- cstats.stub!(:gid).and_return(500)
- cstats.stub!(:mode).and_return(0755)
- File.should_receive(:stat).twice.and_return(cstats)
- @directory.load_current_resource
- @directory.current_resource.path.should eql(@new_resource.path)
- @directory.current_resource.owner.should eql(500)
- @directory.current_resource.group.should eql(500)
- @directory.current_resource.mode.should == 00755
- end
-
- it "should create a new directory on create, setting updated to true" do
- @new_resource.path "/tmp/foo"
-
- File.should_receive(:exist?).exactly(3).and_return(false)
- Dir.should_receive(:mkdir).with(@new_resource.path).once.and_return(true)
-
- @directory.should_receive(:set_all_access_controls)
- @directory.stub!(:update_new_file_state)
- @directory.run_action(:create)
- @directory.new_resource.should be_updated
- end
-
- it "should raise an exception if the parent directory does not exist and recursive is false" do
- @new_resource.path "/tmp/some/dir"
- @new_resource.recursive false
- lambda { @directory.run_action(:create) }.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
- end
-
- it "should create a new directory when parent directory does not exist if recursive is true and permissions are correct" do
- @new_resource.path "/path/to/dir"
- @new_resource.recursive true
- File.should_receive(:exist?).with(@new_resource.path).ordered.and_return(false)
- File.should_receive(:exist?).with(@new_resource.path).ordered.and_return(false)
-
- File.should_receive(:exist?).with('/path/to').ordered.and_return(false)
- File.should_receive(:exist?).with('/path').ordered.and_return(true)
- File.should_receive(:writable?).with('/path').ordered.and_return(true)
- File.should_receive(:exist?).with(@new_resource.path).ordered.and_return(false)
-
- FileUtils.should_receive(:mkdir_p).with(@new_resource.path).and_return(true)
- @directory.should_receive(:set_all_access_controls)
- @directory.stub!(:update_new_file_state)
- @directory.run_action(:create)
- @new_resource.should be_updated
- end
-
- # it "should raise an error when creating a directory recursively and permissions do not allow creation" do
+ context "load_current_resource_attrs", :unix_only do
+ it "should load the current resource based on the new resource" do
+ File.stub!(:exist?).and_return(true)
+ cstats = mock("stats")
+ cstats.stub!(:uid).and_return(500)
+ cstats.stub!(:gid).and_return(500)
+ cstats.stub!(:mode).and_return(0755)
+ File.should_receive(:stat).twice.and_return(cstats)
+ @directory.load_current_resource
+ @directory.current_resource.path.should eql(@new_resource.path)
+ @directory.current_resource.owner.should eql(500)
+ @directory.current_resource.group.should eql(500)
+ @directory.current_resource.mode.should == 00755
+ end
+
+ it "should create a new directory on create, setting updated to true" do
+ @new_resource.path "/tmp/foo"
+
+ File.should_receive(:exist?).exactly(3).and_return(false)
+ Dir.should_receive(:mkdir).with(@new_resource.path).once.and_return(true)
+
+ @directory.should_receive(:set_all_access_controls)
+ @directory.stub!(:update_new_file_state)
+ @directory.run_action(:create)
+ @directory.new_resource.should be_updated
+ end
+
+ it "should raise an exception if the parent directory does not exist and recursive is false" do
+ @new_resource.path "/tmp/some/dir"
+ @new_resource.recursive false
+ lambda { @directory.run_action(:create) }.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
+ end
+
+ it "should create a new directory when parent directory does not exist if recursive is true and permissions are correct" do
+ @new_resource.path "/path/to/dir"
+ @new_resource.recursive true
+ File.should_receive(:exist?).with(@new_resource.path).ordered.and_return(false)
+ File.should_receive(:exist?).with(@new_resource.path).ordered.and_return(false)
+
+ File.should_receive(:exist?).with('/path/to').ordered.and_return(false)
+ File.should_receive(:exist?).with('/path').ordered.and_return(true)
+ File.should_receive(:writable?).with('/path').ordered.and_return(true)
+ File.should_receive(:exist?).with(@new_resource.path).ordered.and_return(false)
+
+ FileUtils.should_receive(:mkdir_p).with(@new_resource.path).and_return(true)
+ @directory.should_receive(:set_all_access_controls)
+ @directory.stub!(:update_new_file_state)
+ @directory.run_action(:create)
+ @new_resource.should be_updated
+ end
+
+ # it "should raise an error when creating a directory recursively and permissions do not allow creation" do
+
+ # end
+
+ it "should raise an error when creating a directory when parent directory is a file" do
+ File.should_receive(:directory?).and_return(false)
+ Dir.should_not_receive(:mkdir).with(@new_resource.path)
+ lambda { @directory.run_action(:create) }.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
+ @directory.new_resource.should_not be_updated
+ end
- # end
-
- it "should raise an error when creating a directory when parent directory is a file" do
- File.should_receive(:directory?).and_return(false)
- Dir.should_not_receive(:mkdir).with(@new_resource.path)
- lambda { @directory.run_action(:create) }.should raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
- @directory.new_resource.should_not be_updated
+ it "should not create the directory if it already exists" do
+ stub_file_cstats
+ @new_resource.path "/tmp/foo"
+ File.should_receive(:exist?).exactly(3).and_return(true)
+ Dir.should_not_receive(:mkdir).with(@new_resource.path)
+ @directory.should_receive(:set_all_access_controls)
+ @directory.run_action(:create)
+ end
end
-
- it "should not create the directory if it already exists" do
- stub_file_cstats
- @new_resource.path "/tmp/foo"
- File.should_receive(:exist?).exactly(3).and_return(true)
- Dir.should_not_receive(:mkdir).with(@new_resource.path)
- @directory.should_receive(:set_all_access_controls)
- @directory.run_action(:create)
+
+ context "load_current_resource_attrs", :windows_only do
+ pending "CHEF-3557: Fix implicit resource change collection on Windows"
end
it "should delete the directory if it exists, and is writable with action_delete" do
diff --git a/spec/unit/provider/file_spec.rb b/spec/unit/provider/file_spec.rb
index 13b79e4bd6..28d2aac2b5 100644
--- a/spec/unit/provider/file_spec.rb
+++ b/spec/unit/provider/file_spec.rb
@@ -53,76 +53,82 @@ describe Chef::Provider::File do
@provider.current_resource.content.should eql(nil)
end
- it "should collect the current state of the file on the filesystem and populate current_resource" do
- # test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
-
- # test execution
- @provider.load_current_resource
-
- # post-condition checks
- @provider.current_resource.mode.should == 0600
- @provider.current_resource.owner.should == 0
- @provider.current_resource.group.should == 0
- end
-
- it "should NOT update the new_resource state with the current_resourse state if new_resource state is already specified" do
- # test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
-
- @provider.new_resource.group(1)
- @provider.new_resource.owner(1)
- @provider.new_resource.mode(0644)
-
- # test execution
- @provider.load_current_resource
-
- # post-condition checks
- @provider.new_resource.group.should == 1
- @provider.new_resource.owner.should == 1
- @provider.new_resource.mode.should == 0644
+ context "load_current_resource_attrs", :unix_only do
+ it "should collect the current state of the file on the filesystem and populate current_resource" do
+ # test setup
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
+
+ # test execution
+ @provider.load_current_resource
+
+ # post-condition checks
+ @provider.current_resource.mode.should == 0600
+ @provider.current_resource.owner.should == 0
+ @provider.current_resource.group.should == 0
+ end
+
+ it "should NOT update the new_resource state with the current_resourse state if new_resource state is already specified" do
+ # test setup
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
+
+ @provider.new_resource.group(1)
+ @provider.new_resource.owner(1)
+ @provider.new_resource.mode(0644)
+
+ # test execution
+ @provider.load_current_resource
+
+ # post-condition checks
+ @provider.new_resource.group.should == 1
+ @provider.new_resource.owner.should == 1
+ @provider.new_resource.mode.should == 0644
+ end
+
+ it "should update the new_resource state with the current_resource state if the new_resource state is not specified." do
+ # test setup
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
+
+ @provider.new_resource.group(nil)
+ @provider.new_resource.owner(nil)
+ @provider.new_resource.mode(nil)
+
+ # test execution
+ @provider.load_current_resource
+
+ # post-condition checks
+ @provider.new_resource.group.should eql(@provider.current_resource.group)
+ @provider.new_resource.owner.should eql(@provider.current_resource.owner)
+ @provider.new_resource.mode.should eql(@provider.current_resource.mode)
+ end
+
+ it "should update the new_resource when attempting to set the new state" do
+ # test setup
+ stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
+ # called once in update_new_file_state and once in checksum
+ ::File.should_receive(:stat).twice.with(@provider.new_resource.path).and_return(stat_struct)
+ ::File.should_receive(:directory?).once.with(@provider.new_resource.path).and_return(false)
+
+ @provider.new_resource.group(nil)
+ @provider.new_resource.owner(nil)
+ @provider.new_resource.mode(nil)
+
+ # test exectution
+ @provider.update_new_file_state
+
+ # post-condition checks
+ @provider.new_resource.group.should == 0
+ @provider.new_resource.owner.should == 0
+ @provider.new_resource.mode.should == 0600
+ end
end
- it "should update the new_resource state with the current_resource state if the new_resource state is not specified." do
- # test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- ::File.should_receive(:stat).exactly(3).with(@resource.path).and_return(stat_struct)
-
- @provider.new_resource.group(nil)
- @provider.new_resource.owner(nil)
- @provider.new_resource.mode(nil)
-
- # test execution
- @provider.load_current_resource
-
- # post-condition checks
- @provider.new_resource.group.should eql(@provider.current_resource.group)
- @provider.new_resource.owner.should eql(@provider.current_resource.owner)
- @provider.new_resource.mode.should eql(@provider.current_resource.mode)
+ context "load_current_resource_attrs", :windows_only do
+ pending "CHEF-3557: Fix implicit resource change collection on Windows"
end
- it "should update the new_resource when attempting to set the new state" do
- # test setup
- stat_struct = mock("::File.stat", :mode => 0600, :uid => 0, :gid => 0, :mtime => 10000)
- # called once in update_new_file_state and once in checksum
- ::File.should_receive(:stat).twice.with(@provider.new_resource.path).and_return(stat_struct)
- ::File.should_receive(:directory?).once.with(@provider.new_resource.path).and_return(false)
-
- @provider.new_resource.group(nil)
- @provider.new_resource.owner(nil)
- @provider.new_resource.mode(nil)
-
- # test exectution
- @provider.update_new_file_state
-
- # post-condition checks
- @provider.new_resource.group.should == 0
- @provider.new_resource.owner.should == 0
- @provider.new_resource.mode.should == 0600
-end
-
it "should load a mostly blank current resource if the file specified in new_resource doesn't exist/isn't readable" do
resource = Chef::Resource::File.new("seattle")
resource.path(File.expand_path(File.join(CHEF_SPEC_DATA, "templates", "woot.txt")))
diff --git a/spec/unit/provider/remote_directory_spec.rb b/spec/unit/provider/remote_directory_spec.rb
index 19a17c269f..0171853eb3 100644
--- a/spec/unit/provider/remote_directory_spec.rb
+++ b/spec/unit/provider/remote_directory_spec.rb
@@ -100,6 +100,13 @@ describe Chef::Provider::RemoteDirectory do
after {FileUtils.rm_rf(@destination_dir)}
+ # CHEF-3552
+ it "creates the toplevel directory without error " do
+ @resource.recursive(false)
+ @provider.run_action(:create)
+ ::File.exist?(@destination_dir).should be_true
+ end
+
it "transfers the directory with all contents" do
@provider.run_action(:create)
::File.exist?(@destination_dir + '/remote_dir_file1.txt').should be_true
diff --git a/spec/unit/resource_reporter_spec.rb b/spec/unit/resource_reporter_spec.rb
index bc8e3995f7..51f4ba7c19 100644
--- a/spec/unit/resource_reporter_spec.rb
+++ b/spec/unit/resource_reporter_spec.rb
@@ -413,18 +413,24 @@ describe Chef::ResourceReporter do
@rest_client.should_receive(:post_rest).
with("reports/nodes/spitfire/runs", {:action => :begin}).
and_raise(@error)
- @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
end
it "assumes the feature is not enabled" do
+ @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
@resource_reporter.reporting_enabled?.should be_false
end
it "does not send a resource report to the server" do
+ @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
@rest_client.should_not_receive(:post_rest)
@resource_reporter.run_completed(@node)
end
+ it "prints an error about the 404" do
+ Chef::Log.should_receive(:debug).with(/404/)
+ @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
+ end
+
end
context "when the server returns a 500 to the client" do
@@ -435,18 +441,23 @@ describe Chef::ResourceReporter do
@rest_client.should_receive(:post_rest).
with("reports/nodes/spitfire/runs", {:action => :begin}).
and_raise(@error)
- @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
end
it "assumes the feature is not enabled" do
+ @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
@resource_reporter.reporting_enabled?.should be_false
end
it "does not send a resource report to the server" do
+ @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
@rest_client.should_not_receive(:post_rest)
@resource_reporter.run_completed(@node)
end
+ it "prints an error about the error" do
+ Chef::Log.should_receive(:info).with(/500/)
+ @resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
+ end
end
context "when the server returns a 500 to the client and enable_reporting_url_fatals is true" do
@@ -465,12 +476,12 @@ describe Chef::ResourceReporter do
Chef::Config[:enable_reporting_url_fatals] = @enable_reporting_url_fatals
end
- it "fails the run" do
+ it "fails the run and prints an message about the error" do
+ Chef::Log.should_receive(:error).with(/500/)
lambda {
@resource_reporter.node_load_completed(@node, :expanded_run_list, :config)
}.should raise_error(Net::HTTPServerException)
end
-
end
context "after creating the run history document" do