diff options
-rw-r--r-- | lib/chef/run_lock.rb | 6 | ||||
-rw-r--r-- | spec/functional/run_lock_spec.rb | 17 |
2 files changed, 21 insertions, 2 deletions
diff --git a/lib/chef/run_lock.rb b/lib/chef/run_lock.rb index ffe4d66045..c63895e87b 100644 --- a/lib/chef/run_lock.rb +++ b/lib/chef/run_lock.rb @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +require 'chef/mixin/create_path' + class Chef # == Chef::RunLock @@ -24,6 +26,8 @@ class Chef # Used by Chef::Client to ensure only one instance of chef-client (or solo) # is modifying the system at a time. class RunLock + include Chef::Mixin::CreatePath + attr_reader :runlock attr_reader :runlock_file @@ -48,6 +52,8 @@ class Chef # # The implementation is based on File#flock (see also: flock(2)). def acquire + # ensure the runlock_file path exists + create_path(File.dirname(runlock_file)) @runlock = File.open(runlock_file,'w+') unless runlock.flock(File::LOCK_EX|File::LOCK_NB) # Another chef client running... diff --git a/spec/functional/run_lock_spec.rb b/spec/functional/run_lock_spec.rb index af9bd1aa1f..1efc4ad42d 100644 --- a/spec/functional/run_lock_spec.rb +++ b/spec/functional/run_lock_spec.rb @@ -22,9 +22,22 @@ describe Chef::RunLock do # This behavior is believed to work on windows, but the tests use UNIX APIs. describe "when locking the chef-client run", :unix_only => true do + let(:random_temp_root){ "/tmp/#{Random.rand(Time.now.to_i + Process.pid)}" } + + let(:file_cache_path){ "/var/chef/cache" } + let(:lockfile){ "#{random_temp_root}/this/long/path/does/not/exist/chef-client-running.pid" } + + after(:each){ FileUtils.rm_r(random_temp_root) } + + it "creates the full path to the lockfile" do + run_lock = Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile) + lambda { run_lock.acquire }.should_not raise_error(Errno::ENOENT) + File.should exist(lockfile) + end + it "allows only one chef client run per lockfile" do read, write = IO.pipe - run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") + run_lock = Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile) p1 = fork do run_lock.acquire write.puts 1 @@ -56,7 +69,7 @@ describe Chef::RunLock do it "clears the lock if the process dies unexpectedly" do read, write = IO.pipe - run_lock = Chef::RunLock.new(:file_cache_path => "/var/chef/cache", :lockfile => "/tmp/chef-client-running.pid") + run_lock = Chef::RunLock.new(:file_cache_path => file_cache_path, :lockfile => lockfile) p1 = fork do run_lock.acquire write.puts 1 |