summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerdar Sutay <serdar@opscode.com>2014-11-14 12:35:05 -0800
committerSerdar Sutay <serdar@opscode.com>2014-11-14 12:35:05 -0800
commitf5ec7e9cc0e269eaac284d87f3c3b33a0cf68b6a (patch)
treed625255c4b47ed9c37740c478e3adccf71eb1c17
parent88a210b46a02aa82f8bf80fab7091b23da7720a3 (diff)
downloadchef-f5ec7e9cc0e269eaac284d87f3c3b33a0cf68b6a.tar.gz
Introduct :auto mode for :file_staging_uses_destdir which tries the dest_dir first and falls back to tmpdir when unsuccessful.
-rw-r--r--lib/chef/config.rb10
-rw-r--r--lib/chef/file_content_management/tempfile.rb37
-rw-r--r--spec/unit/provider/file/content_spec.rb25
3 files changed, 61 insertions, 11 deletions
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index d3871c38e8..877abcc2ba 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -560,10 +560,12 @@ class Chef
# used to update files.
default :file_atomic_update, true
- # If false file staging is will be done via tempfiles that are
- # created under ENV['TMP'] otherwise tempfiles will be created in
- # the directory that files are going to reside.
- default :file_staging_uses_destdir, true
+ # There are 3 possible values for this configuration setting.
+ # true => file staging is done in the destination directory
+ # false => file staging is done via tempfiles under ENV['TMP']
+ # :auto => file staging will try using ENV['TMP'] if possible and
+ # will fall back to destination directory if ENV['TMP'] is not usable.
+ default :file_staging_uses_destdir, :auto
# Exit if another run is in progress and the chef-client is unable to
# get the lock before time expires. If nil, no timeout is enforced. (Exits
diff --git a/lib/chef/file_content_management/tempfile.rb b/lib/chef/file_content_management/tempfile.rb
index 61a5ce2a7c..1673dd7a1b 100644
--- a/lib/chef/file_content_management/tempfile.rb
+++ b/lib/chef/file_content_management/tempfile.rb
@@ -17,6 +17,7 @@
#
require "tempfile"
+require 'pry'
class Chef
class FileContentManagement
@@ -35,7 +36,20 @@ class Chef
private
def tempfile_open
- tf = ::Tempfile.open(tempfile_basename, tempfile_dirname)
+ tf = nil
+
+ tempfile_dirnames.each do |tempfile_dirname|
+ begin
+ tf = ::Tempfile.open(tempfile_basename, tempfile_dirname)
+ break
+ rescue Exception => e
+ Chef::Log.debug("Can not create temp file for staging under '#{tempfile_dirname}'.")
+ Chef::Log.debug(e.message)
+ end
+ end
+
+ raise "Staging tempfile can not be created!" if tf.nil?
+
# We always process the tempfile in binmode so that we
# preserve the line endings of the content.
tf.binmode
@@ -53,16 +67,29 @@ class Chef
basename
end
- def tempfile_dirname
+ # Returns the possible directories for the tempfile to be created in.
+ def tempfile_dirnames
# in why-run mode we need to create a Tempfile to compare against, which we will never
# wind up deploying, but our enclosing directory for the destdir may not exist yet, so
# instead we can reliably always create a Tempfile to compare against in Dir::tmpdir
- if Chef::Config[:file_staging_uses_destdir] && !Chef::Config[:why_run]
- ::File.dirname(@new_resource.path)
+ if Chef::Config[:why_run]
+ [ Dir::tmpdir ]
else
- Dir::tmpdir
+ case Chef::Config[:file_staging_uses_destdir]
+ when :auto
+ # In auto mode we try the destination directory first and fallback to ENV['TMP'] if
+ # that doesn't work.
+ [ ::File.dirname(@new_resource.path), Dir::tmpdir ]
+ when true
+ [ ::File.dirname(@new_resource.path) ]
+ when false
+ [ Dir::tmpdir ]
+ else
+ raise "Unknown setting '#{Chef::Config[:file_staging_uses_destdir]}' for Chef::Config[:file_staging_uses_destdir]. Possible values are :auto, true or false."
+ end
end
end
+
end
end
end
diff --git a/spec/unit/provider/file/content_spec.rb b/spec/unit/provider/file/content_spec.rb
index db0753bf8c..0a45d15bc9 100644
--- a/spec/unit/provider/file/content_spec.rb
+++ b/spec/unit/provider/file/content_spec.rb
@@ -70,12 +70,34 @@ describe Chef::Provider::File::Content do
expect(canonicalize_path(content.tempfile.path).start_with?(enclosing_directory)).to be_falsey
end
- it "returns a tempfile in the destdir when :file_desployment_uses_destdir is not set" do
+ it "returns a tempfile in the destdir when :file_deployment_uses_destdir is set" do
Chef::Config[:file_staging_uses_destdir] = true
expect(content.tempfile.path.start_with?(Dir::tmpdir)).to be_falsey
expect(canonicalize_path(content.tempfile.path).start_with?(enclosing_directory)).to be_truthy
end
+ context "when creating a tempfiles in destdir fails" do
+ let(:enclosing_directory) {
+ canonicalize_path("/nonexisting/path")
+ }
+
+ it "returns a tempfile in the tempdir when :file_deployment_uses_destdir is set to :auto" do
+ Chef::Config[:file_staging_uses_destdir] = :auto
+ expect(content.tempfile.path.start_with?(Dir::tmpdir)).to be_truthy
+ expect(canonicalize_path(content.tempfile.path).start_with?(enclosing_directory)).to be_falsey
+ end
+
+ it "fails when :file_desployment_uses_destdir is set" do
+ Chef::Config[:file_staging_uses_destdir] = true
+ expect{content.tempfile}.to raise_error
+ end
+
+ it "returns a tempfile in the tempdir when :file_desployment_uses_destdir is not set" do
+ expect(content.tempfile.path.start_with?(Dir::tmpdir)).to be_truthy
+ expect(canonicalize_path(content.tempfile.path).start_with?(enclosing_directory)).to be_falsey
+ end
+ end
+
end
describe "when the resource does not have a content attribute set" do
@@ -90,4 +112,3 @@ describe Chef::Provider::File::Content do
end
end
-