diff options
author | Serdar Sutay <serdar@opscode.com> | 2014-11-14 12:35:05 -0800 |
---|---|---|
committer | Serdar Sutay <serdar@opscode.com> | 2014-11-14 12:35:05 -0800 |
commit | f5ec7e9cc0e269eaac284d87f3c3b33a0cf68b6a (patch) | |
tree | d625255c4b47ed9c37740c478e3adccf71eb1c17 | |
parent | 88a210b46a02aa82f8bf80fab7091b23da7720a3 (diff) | |
download | chef-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.rb | 10 | ||||
-rw-r--r-- | lib/chef/file_content_management/tempfile.rb | 37 | ||||
-rw-r--r-- | spec/unit/provider/file/content_spec.rb | 25 |
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 - |