diff options
author | Matt <code@deployable.org> | 2013-12-05 12:20:39 +0000 |
---|---|---|
committer | Claire McQuin <claire@getchef.com> | 2014-06-18 15:23:33 -0700 |
commit | d950ec4bea3333e8739630c37156d6b9d06eccda (patch) | |
tree | d280e92372b4fb41642cedf5e957eedd1035553e | |
parent | d8592902ae09980552f8dd57abe9ed9c76851445 (diff) | |
download | chef-d950ec4bea3333e8739630c37156d6b9d06eccda.tar.gz |
CHEF-4600 Add timeout for Chef::Provider::Service::Windows
-rw-r--r-- | lib/chef/provider/service/windows.rb | 22 | ||||
-rw-r--r-- | lib/chef/resource/service.rb | 8 | ||||
-rw-r--r-- | spec/unit/provider/service/windows_spec.rb | 16 |
3 files changed, 33 insertions, 13 deletions
diff --git a/lib/chef/provider/service/windows.rb b/lib/chef/provider/service/windows.rb index ae4f29b1b3..ba2d5d76ed 100644 --- a/lib/chef/provider/service/windows.rb +++ b/lib/chef/provider/service/windows.rb @@ -41,6 +41,8 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service START_PENDING = 'start pending' STOP_PENDING = 'stop pending' + TIMEOUT = 60 + def whyrun_supported? false end @@ -70,13 +72,13 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service Chef::Log.debug "#{@new_resource} starting service using the given start_command" shell_out!(@new_resource.start_command) else - spawn_command_thread do + command_timeout do Win32::Service.start(@new_resource.service_name) wait_for_state(RUNNING) end end @new_resource.updated_by_last_action(true) - else + else raise Chef::Exceptions::Service, "Service #{@new_resource} can't be started from state [#{state}]" end else @@ -92,7 +94,7 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service Chef::Log.debug "#{@new_resource} stopping service using the given stop_command" shell_out!(@new_resource.stop_command) else - spawn_command_thread do + command_timeout do Win32::Service.stop(@new_resource.service_name) wait_for_state(STOPPED) end @@ -175,13 +177,13 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service sleep 1 until current_state == desired_state end - # There ain't no party like a thread party... - def spawn_command_thread - worker = Thread.new do - yield - end - Timeout.timeout(60) do - worker.join + def command_timeout + timeout = @new_resource.timeout if @new_resource.timeout + timeout ||= TIMEOUT + Chef::Log.debug "service command timeout [#{timeout}]" + + Timeout.timeout(timeout) do + yield end end end diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb index c3d009bc55..a7f1aa3470 100644 --- a/lib/chef/resource/service.rb +++ b/lib/chef/resource/service.rb @@ -42,6 +42,7 @@ class Chef @reload_command = nil @init_command = nil @priority = nil + @timeout = nil @action = "nothing" @supports = { :restart => false, :reload => false, :status => false } @allowed_actions.push(:enable, :disable, :start, :stop, :restart, :reload) @@ -155,6 +156,13 @@ class Chef :kind_of => [ Integer, String, Hash ]) end + # timeout only applies to the windows service manager + def timeout(arg=nil) + set_or_return(:timeout, + arg, + :kind_of => Integer ) + end + def parameters(arg=nil) set_or_return( :parameters, diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb index a007e7b984..d60c6f03ff 100644 --- a/spec/unit/provider/service/windows_spec.rb +++ b/spec/unit/provider/service/windows_spec.rb @@ -92,7 +92,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do @provider.start_service @new_resource.updated_by_last_action?.should be_false end - + it "should raise an error if the service is paused" do Win32::Service.stub(:status).with(@new_resource.service_name).and_return( double("StatusStruct", :current_state => "paused")) @@ -112,7 +112,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do @provider.start_service @new_resource.updated_by_last_action?.should be_false end - + it "should fail if the service is in stop_pending" do Win32::Service.stub(:status).with(@new_resource.service_name).and_return( double("StatusStruct", :current_state => "stop pending")) @@ -170,7 +170,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do expect { @provider.stop_service }.to raise_error( Chef::Exceptions::Service ) @new_resource.updated_by_last_action?.should be_false end - + it "should wait and continue if the service is in stop_pending" do Win32::Service.stub(:status).with(@new_resource.service_name).and_return( double("StatusStruct", :current_state => "stop pending"), @@ -191,6 +191,16 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do @new_resource.updated_by_last_action?.should be_false end + it "should pass custom timeout to the stop command if provided" do + Win32::Service.stub!(:status).with(@new_resource.service_name).and_return( + mock("StatusStruct", :current_state => "running")) + @new_resource.timeout 1 + Win32::Service.should_receive(:stop).with(@new_resource.service_name) + Timeout.timeout(2) do + expect { @provider.stop_service }.to raise_error(Timeout::Error) + end + @new_resource.updated_by_last_action?.should be_false + end end describe Chef::Provider::Service::Windows, "restart_service" do |