summaryrefslogtreecommitdiff
path: root/spec/unit/provider/service
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit/provider/service')
-rw-r--r--spec/unit/provider/service/arch_service_spec.rb330
-rw-r--r--spec/unit/provider/service/debian_service_spec.rb254
-rw-r--r--spec/unit/provider/service/freebsd_service_spec.rb379
-rw-r--r--spec/unit/provider/service/gentoo_service_spec.rb144
-rw-r--r--spec/unit/provider/service/init_service_spec.rb212
-rw-r--r--spec/unit/provider/service/insserv_service_spec.rb76
-rw-r--r--spec/unit/provider/service/invokercd_service_spec.rb212
-rw-r--r--spec/unit/provider/service/macosx_spec.rb229
-rw-r--r--spec/unit/provider/service/redhat_spec.rb156
-rw-r--r--spec/unit/provider/service/simple_service_spec.rb171
-rw-r--r--spec/unit/provider/service/solaris_smf_service_spec.rb140
-rw-r--r--spec/unit/provider/service/systemd_service_spec.rb239
-rw-r--r--spec/unit/provider/service/upstart_service_spec.rb314
-rw-r--r--spec/unit/provider/service/windows_spec.rb235
14 files changed, 3091 insertions, 0 deletions
diff --git a/spec/unit/provider/service/arch_service_spec.rb b/spec/unit/provider/service/arch_service_spec.rb
new file mode 100644
index 0000000000..a7afa28da1
--- /dev/null
+++ b/spec/unit/provider/service/arch_service_spec.rb
@@ -0,0 +1,330 @@
+#
+# Author:: Jan Zimmek (<jan.zimmek@web.de>)
+# Author:: AJ Christensen (<aj@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 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'
+require 'ostruct'
+
+
+# most of this code has been ripped from init_service_spec.rb
+# and is only slightly modified to match "arch" needs.
+
+describe Chef::Provider::Service::Arch, "load_current_resource" do
+ before(:each) do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => "ps -ef"}
+
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+ @new_resource.pattern("chef")
+ @new_resource.supports({:status => false})
+
+
+ @provider = Chef::Provider::Service::Arch.new(@new_resource, @run_context)
+
+ ::File.stub!(:exists?).with("/etc/rc.conf").and_return(true)
+ ::File.stub!(:read).with("/etc/rc.conf").and_return("DAEMONS=(network apache sshd)")
+ end
+
+ describe "when first created" do
+ it "should set the current resources service name to the new resources service name" do
+ @provider.stub(:shell_out).and_return(OpenStruct.new(:exitstatus => 0, :stdout => ""))
+ @provider.load_current_resource
+ @provider.current_resource.service_name.should == 'chef'
+ end
+ end
+
+
+ describe "when the service supports status" do
+ before do
+ @new_resource.supports({:status => true})
+ end
+
+ it "should run '/etc/rc.d/service_name status'" do
+ @provider.should_receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 0))
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the the status command returns 0" do
+ @provider.stub!(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 0))
+ @provider.load_current_resource
+ @provider.current_resource.running.should be_true
+ end
+
+ it "should set running to false if the status command returns anything except 0" do
+ @provider.stub!(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 1))
+ @provider.load_current_resource
+ @provider.current_resource.running.should be_false
+ end
+
+ it "should set running to false if the status command raises" do
+ @provider.stub!(:shell_out).with("/etc/rc.d/chef status").and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.load_current_resource
+ @provider.current_resource.running.should be_false
+ end
+
+ end
+
+
+ describe "when a status command has been specified" do
+ before do
+ @new_resource.status_command("/etc/rc.d/chefhasmonkeypants status")
+ end
+
+ it "should run the services status command if one has been specified" do
+ @provider.should_receive(:shell_out).with("/etc/rc.d/chefhasmonkeypants status").and_return(OpenStruct.new(:exitstatus => 0))
+ @provider.load_current_resource
+ end
+
+ end
+
+ it "should raise error if the node has a nil ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => nil}
+ @provider.define_resource_requirements
+ @provider.action = :start
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should raise error if the node has an empty ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => ""}
+ @provider.define_resource_requirements
+ @provider.action = :start
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+
+ it "should fail if file /etc/rc.conf does not exist" do
+ ::File.stub!(:exists?).with("/etc/rc.conf").and_return(false)
+ lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should fail if file /etc/rc.conf does not contain DAEMONS array" do
+ ::File.stub!(:read).with("/etc/rc.conf").and_return("")
+ lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ describe "when discovering service status with ps" do
+ before do
+ @stdout = StringIO.new(<<-DEFAULT_PS)
+aj 7842 5057 0 21:26 pts/2 00:00:06 vi init.rb
+aj 7903 5016 0 21:26 pts/5 00:00:00 /bin/bash
+aj 8119 6041 0 21:34 pts/3 00:00:03 vi init_service_spec.rb
+DEFAULT_PS
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+
+ @node.automatic_attrs[:command] = {:ps => "ps -ef"}
+ end
+
+ it "determines the service is running when it appears in ps" do
+ @stdout = StringIO.new(<<-RUNNING_PS)
+aj 7842 5057 0 21:26 pts/2 00:00:06 chef
+aj 7842 5057 0 21:26 pts/2 00:00:06 poos
+RUNNING_PS
+ @status.stub!(:stdout).and_return(@stdout)
+ @provider.load_current_resource
+ @provider.current_resource.running.should be_true
+ end
+
+ it "determines the service is not running when it does not appear in ps" do
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @provider.current_resource.running.should be_false
+ end
+
+ it "should raise an exception if ps fails" do
+ @provider.stub!(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.load_current_resource
+ @provider.action = :start
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ it "should return existing entries in DAEMONS array" do
+ ::File.stub!(:read).with("/etc/rc.conf").and_return("DAEMONS=(network !apache ssh)")
+ @provider.daemons.should == ['network', '!apache', 'ssh']
+ end
+
+ context "when the current service status is known" do
+ before do
+ @current_resource = Chef::Resource::Service.new("chef")
+ @provider.current_resource = @current_resource
+ end
+
+ describe Chef::Provider::Service::Arch, "enable_service" do
+ # before(:each) do
+ # @new_resource = mock("Chef::Resource::Service",
+ # :null_object => true,
+ # :name => "chef",
+ # :service_name => "chef",
+ # :running => false
+ # )
+ # @new_resource.stub!(:start_command).and_return(false)
+ #
+ # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource)
+ # Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ # end
+
+ it "should add chef to DAEMONS array" do
+ ::File.stub!(:read).with("/etc/rc.conf").and_return("DAEMONS=(network)")
+ @provider.should_receive(:update_daemons).with(['network', 'chef'])
+ @provider.enable_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Arch, "disable_service" do
+ # before(:each) do
+ # @new_resource = mock("Chef::Resource::Service",
+ # :null_object => true,
+ # :name => "chef",
+ # :service_name => "chef",
+ # :running => false
+ # )
+ # @new_resource.stub!(:start_command).and_return(false)
+ #
+ # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource)
+ # Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ # end
+
+ it "should remove chef from DAEMONS array" do
+ ::File.stub!(:read).with("/etc/rc.conf").and_return("DAEMONS=(network chef)")
+ @provider.should_receive(:update_daemons).with(['network', '!chef'])
+ @provider.disable_service()
+ end
+ end
+
+
+ describe Chef::Provider::Service::Arch, "start_service" do
+ # before(:each) do
+ # @new_resource = mock("Chef::Resource::Service",
+ # :null_object => true,
+ # :name => "chef",
+ # :service_name => "chef",
+ # :running => false
+ # )
+ # @new_resource.stub!(:start_command).and_return(false)
+ #
+ # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource)
+ # Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ # end
+
+ it "should call the start command if one is specified" do
+ @new_resource.stub!(:start_command).and_return("/etc/rc.d/chef startyousillysally")
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/chef startyousillysally")
+ @provider.start_service()
+ end
+
+ it "should call '/etc/rc.d/service_name start' if no start command is specified" do
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} start")
+ @provider.start_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Arch, "stop_service" do
+ # before(:each) do
+ # @new_resource = mock("Chef::Resource::Service",
+ # :null_object => true,
+ # :name => "chef",
+ # :service_name => "chef",
+ # :running => false
+ # )
+ # @new_resource.stub!(:stop_command).and_return(false)
+ #
+ # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource)
+ # Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ # end
+
+ it "should call the stop command if one is specified" do
+ @new_resource.stub!(:stop_command).and_return("/etc/rc.d/chef itoldyoutostop")
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/chef itoldyoutostop")
+ @provider.stop_service()
+ end
+
+ it "should call '/etc/rc.d/service_name stop' if no stop command is specified" do
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} stop")
+ @provider.stop_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Arch, "restart_service" do
+ # before(:each) do
+ # @new_resource = mock("Chef::Resource::Service",
+ # :null_object => true,
+ # :name => "chef",
+ # :service_name => "chef",
+ # :running => false
+ # )
+ # @new_resource.stub!(:restart_command).and_return(false)
+ # @new_resource.stub!(:supports).and_return({:restart => false})
+ #
+ # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource)
+ # Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ # end
+
+ it "should call 'restart' on the service_name if the resource supports it" do
+ @new_resource.stub!(:supports).and_return({:restart => true})
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} restart")
+ @provider.restart_service()
+ end
+
+ it "should call the restart_command if one has been specified" do
+ @new_resource.stub!(:restart_command).and_return("/etc/rc.d/chef restartinafire")
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} restartinafire")
+ @provider.restart_service()
+ end
+
+ it "should just call stop, then start when the resource doesn't support restart and no restart_command is specified" do
+ @provider.should_receive(:stop_service)
+ @provider.should_receive(:sleep).with(1)
+ @provider.should_receive(:start_service)
+ @provider.restart_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Arch, "reload_service" do
+ # before(:each) do
+ # @new_resource = mock("Chef::Resource::Service",
+ # :null_object => true,
+ # :name => "chef",
+ # :service_name => "chef",
+ # :running => false
+ # )
+ # @new_resource.stub!(:reload_command).and_return(false)
+ # @new_resource.stub!(:supports).and_return({:reload => false})
+ #
+ # @provider = Chef::Provider::Service::Arch.new(@node, @new_resource)
+ # Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ # end
+
+ it "should call 'reload' on the service if it supports it" do
+ @new_resource.stub!(:supports).and_return({:reload => true})
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} reload")
+ @provider.reload_service()
+ end
+
+ it "should should run the user specified reload command if one is specified and the service doesn't support reload" do
+ @new_resource.stub!(:reload_command).and_return("/etc/rc.d/chef lollerpants")
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} lollerpants")
+ @provider.reload_service()
+ end
+ end
+ end
+end
diff --git a/spec/unit/provider/service/debian_service_spec.rb b/spec/unit/provider/service/debian_service_spec.rb
new file mode 100644
index 0000000000..bea9360561
--- /dev/null
+++ b/spec/unit/provider/service/debian_service_spec.rb
@@ -0,0 +1,254 @@
+#
+# Author:: AJ Christensen (<aj@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 HJK Solutions, LLC
+# 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::Provider::Service::Debian, "load_current_resource" do
+ before(:each) do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => 'fuuuu'}
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+
+ @current_resource = Chef::Resource::Service.new("chef")
+
+ @provider = Chef::Provider::Service::Debian.new(@new_resource, @run_context)
+ @provider.current_resource = @current_resource
+
+ @pid, @stdin, @stdout, @stderr = nil, nil, nil, nil
+
+ end
+
+ it "ensures /usr/sbin/update-rc.d is available" do
+ File.should_receive(:exists?).with("/usr/sbin/update-rc.d").and_return(false)
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements } .should raise_error(Chef::Exceptions::Service)
+ end
+
+ describe "when update-rc.d shows the init script linked to rc*.d/" do
+ before do
+ @provider.stub!(:assert_update_rcd_available)
+
+ result=<<-UPDATE_RC_D_SUCCESS
+Removing any system startup links for /etc/init.d/chef ...
+ /etc/rc0.d/K20chef
+ /etc/rc1.d/K20chef
+ /etc/rc2.d/S20chef
+ /etc/rc3.d/S20chef
+ /etc/rc4.d/S20chef
+ /etc/rc5.d/S20chef
+ /etc/rc6.d/K20chef
+ UPDATE_RC_D_SUCCESS
+ @stdout = StringIO.new(result)
+ @stderr = StringIO.new
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ end
+
+ it "says the service is enabled" do
+ @provider.service_currently_enabled?(@provider.get_priority).should be_true
+ end
+
+ it "stores the 'enabled' state" do
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.load_current_resource.should equal(@current_resource)
+ @current_resource.enabled.should be_true
+ end
+ end
+
+ {"Debian/Lenny and older" => {
+ "linked" => {
+ "stdout" => " Removing any system startup links for /etc/init.d/chef ...
+ /etc/rc0.d/K20chef
+ /etc/rc1.d/K20chef
+ /etc/rc2.d/S20chef
+ /etc/rc3.d/S20chef
+ /etc/rc4.d/S20chef
+ /etc/rc5.d/S20chef
+ /etc/rc6.d/K20chef",
+ "stderr" => ""
+ },
+ "not linked" => {
+ "stdout" => " Removing any system startup links for /etc/init.d/chef ...",
+ "stderr" => ""
+ },
+ },
+ "Debian/Squeeze and earlier" => {
+ "linked" => {
+ "stdout" => "update-rc.d: using dependency based boot sequencing",
+ "stderr" => "insserv: remove service /etc/init.d/../rc0.d/K20chef-client
+insserv: remove service /etc/init.d/../rc1.d/K20chef-client
+insserv: remove service /etc/init.d/../rc2.d/S20chef-client
+insserv: remove service /etc/init.d/../rc3.d/S20chef-client
+insserv: remove service /etc/init.d/../rc4.d/S20chef-client
+insserv: remove service /etc/init.d/../rc5.d/S20chef-client
+insserv: remove service /etc/init.d/../rc6.d/K20chef-client
+insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop"
+ },
+ "not linked" => {
+ "stdout" => "update-rc.d: using dependency based boot sequencing",
+ "stderr" => ""
+ }
+ }
+ }.each do |model, streams|
+ describe "when update-rc.d shows the init script linked to rc*.d/" do
+ before do
+ @provider.stub!(:assert_update_rcd_available)
+
+ @stdout = StringIO.new(streams["linked"]["stdout"])
+ @stderr = StringIO.new(streams["linked"]["stderr"])
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ end
+
+ it "says the service is enabled" do
+ @provider.service_currently_enabled?(@provider.get_priority).should be_true
+ end
+
+ it "stores the 'enabled' state" do
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.load_current_resource.should equal(@current_resource)
+ @current_resource.enabled.should be_true
+ end
+
+ it "stores the start/stop priorities of the service" do
+ @provider.load_current_resource
+ expected_priorities = {"6"=>[:stop, "20"],
+ "0"=>[:stop, "20"],
+ "1"=>[:stop, "20"],
+ "2"=>[:start, "20"],
+ "3"=>[:start, "20"],
+ "4"=>[:start, "20"],
+ "5"=>[:start, "20"]}
+ @provider.current_resource.priority.should == expected_priorities
+ end
+ end
+
+ describe "when using squeeze/earlier and update-rc.d shows the init script isn't linked to rc*.d" do
+ before do
+ @provider.stub!(:assert_update_rcd_available)
+ @stdout = StringIO.new(streams["not linked"]["stdout"])
+ @stderr = StringIO.new(streams["not linked"]["stderr"])
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ end
+
+ it "says the service is disabled" do
+ @provider.service_currently_enabled?(@provider.get_priority).should be_false
+ end
+
+ it "stores the 'disabled' state" do
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.load_current_resource.should equal(@current_resource)
+ @current_resource.enabled.should be_false
+ end
+ end
+ end
+
+ describe "when update-rc.d shows the init script isn't linked to rc*.d" do
+ before do
+ @provider.stub!(:assert_update_rcd_available)
+ @status = mock("Status", :exitstatus => 0)
+ @stdout = StringIO.new(" Removing any system startup links for /etc/init.d/chef ...")
+ @stderr = StringIO.new
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ end
+
+ it "says the service is disabled" do
+ @provider.service_currently_enabled?(@provider.get_priority).should be_false
+ end
+
+ it "stores the 'disabled' state" do
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.load_current_resource.should equal(@current_resource)
+ @current_resource.enabled.should be_false
+ end
+ end
+
+ describe "when update-rc.d fails" do
+ before do
+ @status = mock("Status", :exitstatus => -1)
+ @provider.stub!(:popen4).and_return(@status)
+ end
+
+ it "raises an error" do
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ describe "when enabling a service without priority" do
+ it "should call update-rc.d 'service_name' defaults" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"})
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults"})
+ @provider.enable_service()
+ end
+ end
+
+ describe "when enabling a service with simple priority" do
+ before do
+ @new_resource.priority(75)
+ end
+
+ it "should call update-rc.d 'service_name' defaults" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"})
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} defaults 75 25"})
+ @provider.enable_service()
+ end
+ end
+
+ describe "when enabling a service with complex priorities" do
+ before do
+ @new_resource.priority(2 => [:start, 20], 3 => [:stop, 55])
+ end
+
+ it "should call update-rc.d 'service_name' defaults" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"})
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d #{@new_resource.service_name} start 20 2 . stop 55 3 . "})
+ @provider.enable_service()
+ end
+ end
+
+ describe "when disabling a service without a priority" do
+
+ it "should call update-rc.d -f 'service_name' remove + stop with a default priority" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"})
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop 80 2 3 4 5 ."})
+ @provider.disable_service()
+ end
+ end
+
+ describe "when disabling a service with simple priority" do
+ before do
+ @new_resource.priority(75)
+ end
+
+ it "should call update-rc.d -f 'service_name' remove + stop with a specified priority" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} remove"})
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/update-rc.d -f #{@new_resource.service_name} stop #{100 - @new_resource.priority} 2 3 4 5 ."})
+ @provider.disable_service()
+ end
+ end
+end
diff --git a/spec/unit/provider/service/freebsd_service_spec.rb b/spec/unit/provider/service/freebsd_service_spec.rb
new file mode 100644
index 0000000000..6dd06bde2c
--- /dev/null
+++ b/spec/unit/provider/service/freebsd_service_spec.rb
@@ -0,0 +1,379 @@
+#
+# Author:: Bryan McLellan (btm@loftninjas.org)
+# Copyright:: Copyright (c) 2009 Bryan McLellan
+# 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::Provider::Service::Freebsd do
+ before do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => "ps -ax"}
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("apache22")
+ @new_resource.pattern("httpd")
+ @new_resource.supports({:status => false})
+
+ @current_resource = Chef::Resource::Service.new("apache22")
+
+ @provider = Chef::Provider::Service::Freebsd.new(@new_resource,@run_context)
+ @provider.action = :start
+ @init_command = "/usr/local/etc/rc.d/apache22"
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ end
+
+ describe "load_current_resource" do
+ before(:each) do
+ @stdout = StringIO.new(<<-PS_SAMPLE)
+413 ?? Ss 0:02.51 /usr/sbin/syslogd -s
+539 ?? Is 0:00.14 /usr/sbin/sshd
+545 ?? Ss 0:17.53 sendmail: accepting connections (sendmail)
+PS_SAMPLE
+ @status = mock(:stdout => @stdout, :exitstatus => 0)
+ @provider.stub!(:shell_out!).with(@node[:command][:ps]).and_return(@status)
+
+ ::File.stub!(:exists?).and_return(false)
+ ::File.stub!(:exists?).with("/usr/local/etc/rc.d/#{@new_resource.service_name}").and_return(true)
+ @lines = mock("lines")
+ @lines.stub!(:each).and_yield("sshd_enable=\"YES\"").
+ and_yield("#{@new_resource.name}_enable=\"YES\"")
+ ::File.stub!(:open).and_return(@lines)
+
+ @rc_with_name = StringIO.new(<<-RC_SAMPLE)
+name="apache22"
+rcvar=`set_rcvar`
+RC_SAMPLE
+ ::File.stub!(:open).with("/usr/local/etc/rc.d/#{@new_resource.service_name}").and_return(@rc_with_name)
+ @provider.stub(:service_enable_variable_name).and_return nil
+
+ end
+
+ it "should create a current resource with the name of the new resource" do
+ Chef::Resource::Service.should_receive(:new).and_return(@current_resource)
+ @provider.load_current_resource
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @provider.load_current_resource
+ @current_resource.service_name.should == @new_resource.service_name
+ end
+
+ it "should not raise an exception if the rcscript have a name variable" do
+ @provider.load_current_resource
+ lambda { @provider.service_enable_variable_name }.should_not raise_error(Chef::Exceptions::Service)
+ end
+
+ describe "when the service supports status" do
+ before do
+ @new_resource.supports({:status => true})
+ end
+
+ it "should run '/etc/init.d/service_name status'" do
+ @provider.should_receive(:shell_out).with("/usr/local/etc/rc.d/#{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the the status command returns 0" do
+ @provider.should_receive(:shell_out).with("/usr/local/etc/rc.d/#{@current_resource.service_name} status").and_return(@status)
+ @current_resource.should_receive(:running).with(true)
+ @provider.load_current_resource
+ end
+
+ it "should set running to false if the status command returns anything except 0" do
+ @provider.should_receive(:shell_out).with("/usr/local/etc/rc.d/#{@current_resource.service_name} status").and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ # @provider.current_resource.running.should be_false
+ end
+ end
+
+ describe "when a status command has been specified" do
+ before do
+ @new_resource.status_command("/bin/chefhasmonkeypants status")
+ end
+
+ it "should run the services status command if one has been specified" do
+ @provider.should_receive(:shell_out).with("/bin/chefhasmonkeypants status").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ end
+
+ it "should raise error if the node has a nil ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => nil}
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should raise error if the node has an empty ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => ""}
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ describe "when executing assertions" do
+ it "should verify that /etc/rc.conf exists" do
+ ::File.should_receive(:exists?).with("/etc/rc.conf")
+ @provider.stub!(:service_enable_variable_name).and_return("#{@current_resource.service_name}_enable")
+ @provider.load_current_resource
+ end
+
+ context "and the init script is not found" do
+ [ "start", "reload", "restart", "enable" ].each do |action|
+ it "should raise an exception when the action is #{action}" do
+ ::File.stub!(:exists?).and_return(false)
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ @provider.instance_variable_get("@rcd_script_found").should be_false
+ @provider.action = action
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ [ "stop", "disable" ].each do |action|
+ it "should not raise an error when the action is #{action}" do
+ @provider.action = action
+ lambda { @provider.process_resource_requirements }.should_not raise_error
+ end
+ end
+ end
+
+ it "update state when current resource enabled state could not be determined" do
+ ::File.should_receive(:exists?).with("/etc/rc.conf").and_return false
+ @provider.load_current_resource
+ @provider.instance_variable_get("@enabled_state_found").should be_false
+ end
+
+ it "update state when current resource enabled state could be determined" do
+ ::File.stub!(:exist?).with("/usr/local/etc/rc.d/#{@new_resource.service_name}").and_return(true)
+ ::File.should_receive(:exists?).with("/etc/rc.conf").and_return true
+ @provider.load_current_resource
+ @provider.instance_variable_get("@enabled_state_found").should be_false
+ @provider.instance_variable_get("@rcd_script_found").should be_true
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service,
+ "Could not find the service name in /usr/local/etc/rc.d/#{@current_resource.service_name} and rcvar")
+ end
+
+ it "should throw an exception if service line is missing from rc.d script" do
+ pending "not implemented" do
+ false.should be_true
+ end
+ end
+
+ end
+
+ describe "when we have a 'ps' attribute" do
+ before do
+ @node.automatic_attrs[:command] = {:ps => "ps -ax"}
+ end
+
+ it "should shell_out! the node's ps command" do
+ @provider.should_receive(:shell_out!).with(@node[:command][:ps]).and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should read stdout of the ps command" do
+ @provider.stub!(:shell_out!).and_return(@status)
+ @stdout.should_receive(:each_line).and_return(true)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the regex matches the output" do
+ @stdout.stub!(:each_line).and_yield("555 ?? Ss 0:05.16 /usr/sbin/cron -s").
+ and_yield(" 9881 ?? Ss 0:06.67 /usr/local/sbin/httpd -DNOHTTPACCEPT")
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the regex doesn't match" do
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+
+ it "should raise an exception if ps fails" do
+ @provider.stub!(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+
+ describe "when starting the service" do
+ it "should call the start command if one is specified" do
+ @new_resource.start_command("/etc/rc.d/chef startyousillysally")
+ @provider.should_receive(:shell_out!).with("/etc/rc.d/chef startyousillysally")
+ @provider.load_current_resource
+ @provider.start_service()
+ end
+
+ it "should call '/usr/local/etc/rc.d/service_name faststart' if no start command is specified" do
+ @provider.should_receive(:shell_out!).with("/usr/local/etc/rc.d/#{@new_resource.service_name} faststart")
+ @provider.load_current_resource
+ @provider.start_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Init, "stop_service" do
+ it "should call the stop command if one is specified" do
+ @new_resource.stop_command("/etc/init.d/chef itoldyoutostop")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/chef itoldyoutostop")
+ @provider.load_current_resource
+ @provider.stop_service()
+ end
+
+ it "should call '/usr/local/etc/rc.d/service_name faststop' if no stop command is specified" do
+ @provider.should_receive(:shell_out!).with("/usr/local/etc/rc.d/#{@new_resource.service_name} faststop")
+ @provider.load_current_resource
+ @provider.stop_service()
+ end
+ end
+
+ describe "when restarting a service" do
+ it "should call 'restart' on the service_name if the resource supports it" do
+ @new_resource.supports({:restart => true})
+ @provider.should_receive(:shell_out!).with("/usr/local/etc/rc.d/#{@new_resource.service_name} fastrestart")
+ @provider.load_current_resource
+ @provider.restart_service()
+ end
+
+ it "should call the restart_command if one has been specified" do
+ @new_resource.restart_command("/etc/init.d/chef restartinafire")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/chef restartinafire")
+ @provider.load_current_resource
+ @provider.restart_service()
+ end
+ end
+
+ describe "when the rcscript does not have a name variable" do
+ before do
+ @rc_without_name = StringIO.new(<<-RC_SAMPLE)
+rcvar=`set_rcvar`
+RC_SAMPLE
+ ::File.stub!(:open).with("/usr/local/etc/rc.d/#{@current_resource.service_name}").and_return(@rc_with_noname)
+ @provider.current_resource = @current_resource
+ end
+
+ describe "when rcvar returns foobar_enable" do
+ before do
+ @rcvar_stdout = <<RCVAR_SAMPLE
+# apache22
+#
+# #{@current_resource.service_name}_enable="YES"
+# (default: "")
+RCVAR_SAMPLE
+ @status = mock(:stdout => @rcvar_stdout, :exitstatus => 0)
+ @provider.stub!(:shell_out!).with("/usr/local/etc/rc.d/#{@current_resource.service_name} rcvar").and_return(@status)
+ end
+
+ it "should get the service name from rcvar if the rcscript does not have a name variable" do
+ @provider.load_current_resource
+ @provider.unstub!(:service_enable_variable_name)
+ @provider.service_enable_variable_name.should == "#{@current_resource.service_name}_enable"
+ end
+
+ it "should not raise an exception if the rcscript does not have a name variable" do
+ @provider.load_current_resource
+ lambda { @provider.service_enable_variable_name }.should_not raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ describe "when rcvar does not return foobar_enable" do
+ before do
+ @rcvar_stdout = <<RCVAR_SAMPLE
+# service_with_noname
+#
+RCVAR_SAMPLE
+ @status = mock(:stdout => @rcvar_stdout, :exitstatus => 0)
+ @provider.stub!(:shell_out!).with("/usr/local/etc/rc.d/#{@current_resource.service_name} rcvar").and_return(@status)
+ end
+
+ [ "start", "reload", "restart", "enable" ].each do |action|
+ it "should raise an exception when the action is #{action}" do
+ @provider.action = action
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ [ "stop", "disable" ].each do |action|
+ it "should not raise an error when the action is #{action}" do
+ ::File.stub!(:exist?).with("/usr/local/etc/rc.d/#{@new_resource.service_name}").and_return(true)
+ @provider.action = action
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should_not raise_error(Chef::Exceptions::Service)
+ end
+ end
+ end
+ end
+ end
+
+ describe Chef::Provider::Service::Freebsd, "enable_service" do
+ before do
+ @provider.current_resource = @current_resource
+ @provider.stub!(:service_enable_variable_name).and_return("#{@current_resource.service_name}_enable")
+ end
+
+ it "should enable the service if it is not enabled" do
+ @current_resource.stub!(:enabled).and_return(false)
+ @provider.should_receive(:read_rc_conf).and_return([ "foo", "#{@current_resource.service_name}_enable=\"NO\"", "bar" ])
+ @provider.should_receive(:write_rc_conf).with(["foo", "bar", "#{@current_resource.service_name}_enable=\"YES\""])
+ @provider.enable_service()
+ end
+
+ it "should enable the service if it is not enabled and not already specified in the rc.conf file" do
+ @current_resource.stub!(:enabled).and_return(false)
+ @provider.should_receive(:read_rc_conf).and_return([ "foo", "bar" ])
+ @provider.should_receive(:write_rc_conf).with(["foo", "bar", "#{@current_resource.service_name}_enable=\"YES\""])
+ @provider.enable_service()
+ end
+
+ it "should not enable the service if it is already enabled" do
+ @current_resource.stub!(:enabled).and_return(true)
+ @provider.should_not_receive(:write_rc_conf)
+ @provider.enable_service
+ end
+ end
+
+ describe Chef::Provider::Service::Freebsd, "disable_service" do
+ before do
+ @provider.current_resource = @current_resource
+ @provider.stub!(:service_enable_variable_name).and_return("#{@current_resource.service_name}_enable")
+ end
+
+ it "should should disable the service if it is not disabled" do
+ @current_resource.stub!(:enabled).and_return(true)
+ @provider.should_receive(:read_rc_conf).and_return([ "foo", "#{@current_resource.service_name}_enable=\"YES\"", "bar" ])
+ @provider.should_receive(:write_rc_conf).with(["foo", "bar", "#{@current_resource.service_name}_enable=\"NO\""])
+ @provider.disable_service()
+ end
+
+ it "should not disable the service if it is already disabled" do
+ @current_resource.stub!(:enabled).and_return(false)
+ @provider.should_not_receive(:write_rc_conf)
+ @provider.disable_service()
+ end
+ end
+end
diff --git a/spec/unit/provider/service/gentoo_service_spec.rb b/spec/unit/provider/service/gentoo_service_spec.rb
new file mode 100644
index 0000000000..8d4ada043b
--- /dev/null
+++ b/spec/unit/provider/service/gentoo_service_spec.rb
@@ -0,0 +1,144 @@
+#
+# Author:: Lee Jensen (<ljensen@engineyard.com>)
+# Author:: AJ Christensen (<aj@opscode.com>)
+# Copyright:: Copyright (c) 2008 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::Provider::Service::Gentoo do
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+ @current_resource = Chef::Resource::Service.new("chef")
+
+ @provider = Chef::Provider::Service::Gentoo.new(@new_resource, @run_context)
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out).and_return(@status)
+ File.stub!(:exists?).with("/etc/init.d/chef").and_return(true)
+ File.stub!(:exists?).with("/sbin/rc-update").and_return(true)
+ File.stub!(:exists?).with("/etc/runlevels/default/chef").and_return(false)
+ File.stub!(:readable?).with("/etc/runlevels/default/chef").and_return(false)
+ end
+ # new test: found_enabled state
+ #
+ describe "load_current_resource" do
+ it "should raise Chef::Exceptions::Service if /sbin/rc-update does not exist" do
+ File.should_receive(:exists?).with("/sbin/rc-update").and_return(false)
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should track when service file is not found in /etc/runlevels" do
+ @provider.load_current_resource
+ @provider.instance_variable_get("@found_script").should be_false
+ end
+
+ it "should track when service file is found in /etc/runlevels/**/" do
+ Dir.stub!(:glob).with("/etc/runlevels/**/chef").and_return(["/etc/runlevels/default/chef"])
+ @provider.load_current_resource
+ @provider.instance_variable_get("@found_script").should be_true
+ end
+
+ describe "when detecting the service enable state" do
+ describe "and the glob returns a default service script file" do
+ before do
+ Dir.stub!(:glob).with("/etc/runlevels/**/chef").and_return(["/etc/runlevels/default/chef"])
+ end
+
+ describe "and the file exists and is readable" do
+ before do
+ File.stub!(:exists?).with("/etc/runlevels/default/chef").and_return(true)
+ File.stub!(:readable?).with("/etc/runlevels/default/chef").and_return(true)
+ end
+ it "should set enabled to true" do
+ @provider.load_current_resource
+ @current_resource.enabled.should be_true
+ end
+ end
+
+ describe "and the file exists but is not readable" do
+ before do
+ File.stub!(:exists?).with("/etc/runlevels/default/chef").and_return(true)
+ File.stub!(:readable?).with("/etc/runlevels/default/chef").and_return(false)
+ end
+
+ it "should set enabled to false" do
+ @provider.load_current_resource
+ @current_resource.enabled.should be_false
+ end
+ end
+
+ describe "and the file does not exist" do
+ before do
+ File.stub!(:exists?).with("/etc/runlevels/default/chef").and_return(false)
+ File.stub!(:readable?).with("/etc/runlevels/default/chef").and_return("foobarbaz")
+ end
+
+ it "should set enabled to false" do
+ @provider.load_current_resource
+ @current_resource.enabled.should be_false
+ end
+
+ end
+ end
+
+ end
+
+ it "should return the current_resource" do
+ @provider.load_current_resource.should == @current_resource
+ end
+
+ it "should support the status command automatically" do
+ @provider.load_current_resource
+ @new_resource.supports[:status].should be_true
+ end
+
+ it "should support the restart command automatically" do
+ @provider.load_current_resource
+ @new_resource.supports[:restart].should be_true
+ end
+
+ it "should not support the reload command automatically" do
+ @provider.load_current_resource
+ @new_resource.supports[:reload].should_not be_true
+ end
+
+ end
+
+ describe "action_methods" do
+ before(:each) { @provider.stub!(:load_current_resource).and_return(@current_resource) }
+
+ describe Chef::Provider::Service::Gentoo, "enable_service" do
+ it "should call rc-update add *service* default" do
+ @provider.should_receive(:run_command).with({:command => "/sbin/rc-update add chef default"})
+ @provider.enable_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Gentoo, "disable_service" do
+ it "should call rc-update del *service* default" do
+ @provider.should_receive(:run_command).with({:command => "/sbin/rc-update del chef default"})
+ @provider.disable_service()
+ end
+ end
+ end
+
+end
diff --git a/spec/unit/provider/service/init_service_spec.rb b/spec/unit/provider/service/init_service_spec.rb
new file mode 100644
index 0000000000..77b22c8cf4
--- /dev/null
+++ b/spec/unit/provider/service/init_service_spec.rb
@@ -0,0 +1,212 @@
+#
+# Author:: AJ Christensen (<aj@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 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::Provider::Service::Init, "load_current_resource" do
+ before(:each) do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => "ps -ef"}
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+
+ @current_resource = Chef::Resource::Service.new("chef")
+
+ @provider = Chef::Provider::Service::Init.new(@new_resource, @run_context)
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+
+ @stdout = StringIO.new(<<-PS)
+aj 7842 5057 0 21:26 pts/2 00:00:06 vi init.rb
+aj 7903 5016 0 21:26 pts/5 00:00:00 /bin/bash
+aj 8119 6041 0 21:34 pts/3 00:00:03 vi init_service_spec.rb
+PS
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ end
+
+ it "should create a current resource with the name of the new resource" do
+ @provider.load_current_resource
+ @provider.current_resource.should equal(@current_resource)
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @provider.load_current_resource
+ @current_resource.service_name.should == 'chef'
+ end
+
+ describe "when the service supports status" do
+ before do
+ @new_resource.supports({:status => true})
+ end
+
+ it "should run '/etc/init.d/service_name status'" do
+ @provider.should_receive(:shell_out).with("/etc/init.d/#{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the the status command returns 0" do
+ @provider.stub!(:shell_out).with("/etc/init.d/#{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the status command returns anything except 0" do
+ @status.stub!(:exitstatus).and_return(1)
+ @provider.stub!(:shell_out).with("/etc/init.d/#{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+
+ it "should set running to false if the status command raises" do
+ @provider.stub!(:shell_out).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+ end
+
+ describe "when a status command has been specified" do
+ before do
+ @new_resource.stub!(:status_command).and_return("/etc/init.d/chefhasmonkeypants status")
+ end
+
+ it "should run the services status command if one has been specified" do
+ @provider.should_receive(:shell_out).with("/etc/init.d/chefhasmonkeypants status").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ end
+
+ describe "when the node has not specified a ps command" do
+
+ it "should raise an error if the node has a nil ps attribute" do
+ @node.automatic_attrs[:command] = {:ps => nil}
+ @provider.load_current_resource
+ @provider.action = :start
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should raise an error if the node has an empty ps attribute" do
+ @node.automatic_attrs[:command] = {:ps => ""}
+ @provider.load_current_resource
+ @provider.action = :start
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ end
+
+
+ describe "when we have a 'ps' attribute" do
+ it "should shell_out! the node's ps command" do
+ @provider.should_receive(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the regex matches the output" do
+ @stdout = StringIO.new(<<-RUNNING_PS)
+aj 7842 5057 0 21:26 pts/2 00:00:06 chef
+aj 7842 5057 0 21:26 pts/2 00:00:06 poos
+RUNNING_PS
+ @status.stub!(:stdout).and_return(@stdout)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the regex doesn't match" do
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+
+ it "should raise an exception if ps fails" do
+ @provider.stub!(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.load_current_resource
+ @provider.action = :start
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+
+ describe "when starting the service" do
+ it "should call the start command if one is specified" do
+ @new_resource.start_command("/etc/init.d/chef startyousillysally")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/chef startyousillysally")
+ @provider.start_service()
+ end
+
+ it "should call '/etc/init.d/service_name start' if no start command is specified" do
+ @provider.should_receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} start")
+ @provider.start_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Init, "stop_service" do
+ it "should call the stop command if one is specified" do
+ @new_resource.stop_command("/etc/init.d/chef itoldyoutostop")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/chef itoldyoutostop")
+ @provider.stop_service()
+ end
+
+ it "should call '/etc/init.d/service_name stop' if no stop command is specified" do
+ @provider.should_receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} stop")
+ @provider.stop_service()
+ end
+ end
+
+ describe "when restarting a service" do
+ it "should call 'restart' on the service_name if the resource supports it" do
+ @new_resource.supports({:restart => true})
+ @provider.should_receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} restart")
+ @provider.restart_service()
+ end
+
+ it "should call the restart_command if one has been specified" do
+ @new_resource.restart_command("/etc/init.d/chef restartinafire")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} restartinafire")
+ @provider.restart_service()
+ end
+
+ it "should just call stop, then start when the resource doesn't support restart and no restart_command is specified" do
+ @provider.should_receive(:stop_service)
+ @provider.should_receive(:sleep).with(1)
+ @provider.should_receive(:start_service)
+ @provider.restart_service()
+ end
+ end
+
+ describe "when reloading a service" do
+ it "should call 'reload' on the service if it supports it" do
+ @new_resource.supports({:reload => true})
+ @provider.should_receive(:shell_out!).with("/etc/init.d/chef reload")
+ @provider.reload_service()
+ end
+
+ it "should should run the user specified reload command if one is specified and the service doesn't support reload" do
+ @new_resource.reload_command("/etc/init.d/chef lollerpants")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/chef lollerpants")
+ @provider.reload_service()
+ end
+ end
+end
diff --git a/spec/unit/provider/service/insserv_service_spec.rb b/spec/unit/provider/service/insserv_service_spec.rb
new file mode 100644
index 0000000000..c823d511b5
--- /dev/null
+++ b/spec/unit/provider/service/insserv_service_spec.rb
@@ -0,0 +1,76 @@
+#
+# Author:: Bryan McLellan <btm@loftninjas.org>
+# Copyright:: Copyright (c) 2011 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::Provider::Service::Insserv do
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+ @node.automatic_attrs[:command] = {:ps => "ps -ax"}
+
+ @new_resource = Chef::Resource::Service.new("initgrediant")
+ @current_resource = Chef::Resource::Service.new("initgrediant")
+
+ @provider = Chef::Provider::Service::Insserv.new(@new_resource, @run_context)
+ @status = mock("Process::Status mock", :exitstatus => 0, :stdout => "")
+ @provider.stub!(:shell_out!).and_return(@status)
+ end
+
+ describe "load_current_resource" do
+ describe "when startup links exist" do
+ before do
+ Dir.stub!(:glob).with("/etc/rc**/S*initgrediant").and_return(["/etc/rc5.d/S18initgrediant", "/etc/rc2.d/S18initgrediant", "/etc/rc4.d/S18initgrediant", "/etc/rc3.d/S18initgrediant"])
+ end
+
+ it "sets the current enabled status to true" do
+ @provider.load_current_resource
+ @provider.current_resource.enabled.should be_true
+ end
+ end
+
+ describe "when startup links do not exist" do
+ before do
+ Dir.stub!(:glob).with("/etc/rc**/S*initgrediant").and_return([])
+ end
+
+ it "sets the current enabled status to false" do
+ @provider.load_current_resource
+ @provider.current_resource.enabled.should be_false
+ end
+ end
+
+ end
+
+ describe "enable_service" do
+ it "should call insserv and create the default links" do
+ @provider.should_receive(:run_command).with({:command=>"/sbin/insserv -r -f #{@new_resource.service_name}"})
+ @provider.should_receive(:run_command).with({:command=>"/sbin/insserv -d -f #{@new_resource.service_name}"})
+ @provider.enable_service
+ end
+ end
+
+ describe "disable_service" do
+ it "should call insserv and remove the links" do
+ @provider.should_receive(:run_command).with({:command=>"/sbin/insserv -r -f #{@new_resource.service_name}"})
+ @provider.disable_service
+ end
+ end
+end
+
diff --git a/spec/unit/provider/service/invokercd_service_spec.rb b/spec/unit/provider/service/invokercd_service_spec.rb
new file mode 100644
index 0000000000..ace2ad24e3
--- /dev/null
+++ b/spec/unit/provider/service/invokercd_service_spec.rb
@@ -0,0 +1,212 @@
+#
+# Author:: AJ Christensen (<aj@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 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::Provider::Service::Invokercd, "load_current_resource" do
+ before(:each) do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => "ps -ef"}
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+
+ @current_resource = Chef::Resource::Service.new("chef")
+
+ @provider = Chef::Provider::Service::Invokercd.new(@new_resource, @run_context)
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+
+ @stdout = StringIO.new(<<-PS)
+aj 7842 5057 0 21:26 pts/2 00:00:06 vi init.rb
+aj 7903 5016 0 21:26 pts/5 00:00:00 /bin/bash
+aj 8119 6041 0 21:34 pts/3 00:00:03 vi init_service_spec.rb
+PS
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ end
+
+ it "should create a current resource with the name of the new resource" do
+ @provider.load_current_resource
+ @provider.current_resource.should equal(@current_resource)
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @provider.load_current_resource
+ @current_resource.service_name.should == 'chef'
+ end
+
+ describe "when the service supports status" do
+ before do
+ @new_resource.supports({:status => true})
+ end
+
+ it "should run '/usr/sbin/invoke-rc.d service_name status'" do
+ @provider.should_receive(:shell_out).with("/usr/sbin/invoke-rc.d #{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the the status command returns 0" do
+ @provider.stub!(:shell_out).with("/usr/sbin/invoke-rc.d #{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the status command returns anything except 0" do
+ @status.stub!(:exitstatus).and_return(1)
+ @provider.stub!(:shell_out).with("/usr/sbin/invoke-rc.d #{@current_resource.service_name} status").and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+
+ it "should set running to false if the status command raises" do
+ @provider.stub!(:shell_out).with("/usr/sbin/invoke-rc.d #{@current_resource.service_name} status").and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+ end
+
+ describe "when a status command has been specified" do
+ before do
+ @new_resource.stub!(:status_command).and_return("/usr/sbin/invoke-rc.d chefhasmonkeypants status")
+ end
+
+ it "should run the services status command if one has been specified" do
+ @provider.should_receive(:shell_out).with("/usr/sbin/invoke-rc.d chefhasmonkeypants status").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ end
+
+ describe "when the node has not specified a ps command" do
+ it "should raise error if the node has a nil ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => nil}
+ @provider.action = :start
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should raise error if the node has an empty ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => ""}
+ @provider.action = :start
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ end
+
+
+ describe "when we have a 'ps' attribute" do
+ it "should shell_out! the node's ps command" do
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.should_receive(:shell_out!).with(@node[:command][:ps]).and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the regex matches the output" do
+ @stdout = StringIO.new(<<-RUNNING_PS)
+aj 7842 5057 0 21:26 pts/2 00:00:06 chef
+aj 7842 5057 0 21:26 pts/2 00:00:06 poos
+RUNNING_PS
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.should_receive(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the regex doesn't match" do
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.should_receive(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+
+ it "should raise an exception if ps fails" do
+ @provider.stub!(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.action = :start
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+
+ describe "when starting the service" do
+ it "should call the start command if one is specified" do
+ @new_resource.start_command("/usr/sbin/invoke-rc.d chef startyousillysally")
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef startyousillysally")
+ @provider.start_service()
+ end
+
+ it "should call '/usr/sbin/invoke-rc.d service_name start' if no start command is specified" do
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} start")
+ @provider.start_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Invokercd, "stop_service" do
+ it "should call the stop command if one is specified" do
+ @new_resource.stop_command("/usr/sbin/invoke-rc.d chef itoldyoutostop")
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef itoldyoutostop")
+ @provider.stop_service()
+ end
+
+ it "should call '/usr/sbin/invoke-rc.d service_name stop' if no stop command is specified" do
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} stop")
+ @provider.stop_service()
+ end
+ end
+
+ describe "when restarting a service" do
+ it "should call 'restart' on the service_name if the resource supports it" do
+ @new_resource.supports({:restart => true})
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} restart")
+ @provider.restart_service()
+ end
+
+ it "should call the restart_command if one has been specified" do
+ @new_resource.restart_command("/usr/sbin/invoke-rc.d chef restartinafire")
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} restartinafire")
+ @provider.restart_service()
+ end
+
+ it "should just call stop, then start when the resource doesn't support restart and no restart_command is specified" do
+ @provider.should_receive(:stop_service)
+ @provider.should_receive(:sleep).with(1)
+ @provider.should_receive(:start_service)
+ @provider.restart_service()
+ end
+ end
+
+ describe "when reloading a service" do
+ it "should call 'reload' on the service if it supports it" do
+ @new_resource.supports({:reload => true})
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef reload")
+ @provider.reload_service()
+ end
+
+ it "should should run the user specified reload command if one is specified and the service doesn't support reload" do
+ @new_resource.reload_command("/usr/sbin/invoke-rc.d chef lollerpants")
+ @provider.should_receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef lollerpants")
+ @provider.reload_service()
+ end
+ end
+end
diff --git a/spec/unit/provider/service/macosx_spec.rb b/spec/unit/provider/service/macosx_spec.rb
new file mode 100644
index 0000000000..9c3ec340a2
--- /dev/null
+++ b/spec/unit/provider/service/macosx_spec.rb
@@ -0,0 +1,229 @@
+#
+# Author:: Igor Afonov <afonov@gmail.com>
+# Copyright:: Copyright (c) 2011 Igor Afonov
+# 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::Provider::Service::Macosx do
+ let(:node) { Chef::Node.new }
+ let(:events) {Chef::EventDispatch::Dispatcher.new}
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:provider) { described_class.new(new_resource, run_context) }
+ let(:stdout) { StringIO.new }
+
+ before do
+ Dir.stub!(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist"], [])
+ provider.stub!(:shell_out!).
+ with("launchctl list", {:group => 1001, :user => 101}).
+ and_return(mock("ouput", :stdout => stdout))
+
+ File.stub!(:stat).and_return(mock("stat", :gid => 1001, :uid => 101))
+ end
+
+ ["redis-server", "io.redis.redis-server"].each do |service_name|
+ context "when service name is given as #{service_name}" do
+ let(:new_resource) { Chef::Resource::Service.new(service_name) }
+ let!(:current_resource) { Chef::Resource::Service.new(service_name) }
+
+ describe "#load_current_resource" do
+ context "when launchctl returns pid in service list" do
+ let(:stdout) { StringIO.new <<-SVC_LIST }
+12761 - 0x100114220.old.machinit.thing
+7777 - io.redis.redis-server
+- - com.lol.stopped-thing
+SVC_LIST
+
+ before do
+ provider.load_current_resource
+ end
+
+ it "sets resource running state to true" do
+ provider.current_resource.running.should be_true
+ end
+
+ it "sets resouce enabled state to true" do
+ provider.current_resource.enabled.should be_true
+ end
+ end
+
+ describe "running unsupported actions" do
+ before do
+ Dir.stub!(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist"], [])
+ end
+ it "should throw an exception when enable action is attempted" do
+ lambda {provider.run_action(:enable)}.should raise_error(Chef::Exceptions::UnsupportedAction)
+ end
+ it "should throw an exception when reload action is attempted" do
+ lambda {provider.run_action(:reload)}.should raise_error(Chef::Exceptions::UnsupportedAction)
+ end
+ it "should throw an exception when disable action is attempted" do
+ lambda {provider.run_action(:disable)}.should raise_error(Chef::Exceptions::UnsupportedAction)
+ end
+ end
+ context "when launchctl returns empty service pid" do
+ let(:stdout) { StringIO.new <<-SVC_LIST }
+12761 - 0x100114220.old.machinit.thing
+- - io.redis.redis-server
+- - com.lol.stopped-thing
+SVC_LIST
+
+ before do
+ provider.load_current_resource
+ end
+
+ it "sets resource running state to false" do
+ provider.current_resource.running.should be_false
+ end
+
+ it "sets resouce enabled state to true" do
+ provider.current_resource.enabled.should be_true
+ end
+ end
+
+ context "when launchctl doesn't return service entry at all" do
+ let(:stdout) { StringIO.new <<-SVC_LIST }
+12761 - 0x100114220.old.machinit.thing
+- - com.lol.stopped-thing
+SVC_LIST
+
+ it "sets service running state to false" do
+ provider.load_current_resource
+ provider.current_resource.running.should be_false
+ end
+
+ context "and plist for service is not available" do
+ before do
+ Dir.stub!(:glob).and_return([])
+ provider.load_current_resource
+ end
+
+ it "sets resouce enabled state to false" do
+ provider.current_resource.enabled.should be_false
+ end
+ end
+
+ context "and plist for service is available" do
+ before do
+ Dir.stub!(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist"], [])
+ provider.load_current_resource
+ end
+
+ it "sets resouce enabled state to true" do
+ provider.current_resource.enabled.should be_true
+ end
+ end
+
+ describe "and several plists match service name" do
+ it "throws exception" do
+ Dir.stub!(:glob).and_return(["/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist",
+ "/Users/wtf/something.plist"])
+ provider.load_current_resource
+ provider.define_resource_requirements
+ lambda { provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+ end
+ end
+ describe "#start_service" do
+ before do
+ Chef::Resource::Service.stub!(:new).and_return(current_resource)
+ provider.load_current_resource
+ current_resource.stub!(:running).and_return(false)
+ end
+
+ it "calls the start command if one is specified and service is not running" do
+ new_resource.stub!(:start_command).and_return("cowsay dirty")
+
+ provider.should_receive(:shell_out!).with("cowsay dirty")
+ provider.start_service
+ end
+
+ it "shows warning message if service is already running" do
+ current_resource.stub!(:running).and_return(true)
+ Chef::Log.should_receive(:debug).with("service[#{service_name}] already running, not starting")
+
+ provider.start_service
+ end
+
+ it "starts service via launchctl if service found" do
+ provider.should_receive(:shell_out!).
+ with("launchctl load -w '/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist'",
+ :group => 1001, :user => 101).
+ and_return(0)
+
+ provider.start_service
+ end
+ end
+
+ describe "#stop_service" do
+ before do
+ Chef::Resource::Service.stub!(:new).and_return(current_resource)
+
+ provider.load_current_resource
+ current_resource.stub!(:running).and_return(true)
+ end
+
+ it "calls the stop command if one is specified and service is running" do
+ new_resource.stub!(:stop_command).and_return("kill -9 123")
+
+ provider.should_receive(:shell_out!).with("kill -9 123")
+ provider.stop_service
+ end
+
+ it "shows warning message if service is not running" do
+ current_resource.stub!(:running).and_return(false)
+ Chef::Log.should_receive(:debug).with("service[#{service_name}] not running, not stopping")
+
+ provider.stop_service
+ end
+
+ it "stops the service via launchctl if service found" do
+ provider.should_receive(:shell_out!).
+ with("launchctl unload '/Users/igor/Library/LaunchAgents/io.redis.redis-server.plist'",
+ :group => 1001, :user => 101).
+ and_return(0)
+
+ provider.stop_service
+ end
+ end
+
+ describe "#restart_service" do
+ before do
+ Chef::Resource::Service.stub!(:new).and_return(current_resource)
+
+ provider.load_current_resource
+ current_resource.stub!(:running).and_return(true)
+ provider.stub!(:sleep)
+ end
+
+ it "issues a command if given" do
+ new_resource.stub!(:restart_command).and_return("reload that thing")
+
+ provider.should_receive(:shell_out!).with("reload that thing")
+ provider.restart_service
+ end
+
+ it "stops and then starts service" do
+ provider.should_receive(:stop_service)
+ provider.should_receive(:start_service);
+
+ provider.restart_service
+ end
+ end
+ end
+ end
+end
diff --git a/spec/unit/provider/service/redhat_spec.rb b/spec/unit/provider/service/redhat_spec.rb
new file mode 100644
index 0000000000..dd874a4f05
--- /dev/null
+++ b/spec/unit/provider/service/redhat_spec.rb
@@ -0,0 +1,156 @@
+#
+# Author:: AJ Christensen (<aj@hjksolutions.com>)
+# Copyright:: Copyright (c) 2008 HJK Solutions, LLC
+# 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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "spec_helper"))
+require 'ostruct'
+
+shared_examples_for "define_resource_requirements_common" do
+ it "should raise an error if /sbin/chkconfig does not exist" do
+ File.stub!(:exists?).with("/sbin/chkconfig").and_return(false)
+ @provider.stub!(:shell_out).with("/sbin/service chef status").and_raise(Errno::ENOENT)
+ @provider.stub!(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0,1]).and_raise(Errno::ENOENT)
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should not raise an error if the service exists but is not added to any runlevels" do
+ status = mock("Status", :exitstatus => 0, :stdout => "" , :stderr => "")
+ @provider.should_receive(:shell_out).with("/sbin/service chef status").and_return(status)
+ chkconfig = mock("Chkconfig", :exitstatus => 0, :stdout => "", :stderr => "service chef supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add chef')")
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0,1]).and_return(chkconfig)
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should_not raise_error
+ end
+end
+
+describe "Chef::Provider::Service::Redhat" do
+
+ before(:each) do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => 'foo'}
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+
+ @current_resource = Chef::Resource::Service.new("chef")
+
+ @provider = Chef::Provider::Service::Redhat.new(@new_resource, @run_context)
+ @provider.action = :start
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ File.stub!(:exists?).with("/sbin/chkconfig").and_return(true)
+ end
+
+ describe "while not in why run mode" do
+ before(:each) do
+ Chef::Config[:why_run] = false
+ end
+
+ describe "load current resource" do
+ it "sets the current enabled status to true if the service is enabled for any run level" do
+ status = mock("Status", :exitstatus => 0, :stdout => "" , :stderr => "")
+ @provider.should_receive(:shell_out).with("/sbin/service chef status").and_return(status)
+ chkconfig = mock("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", :stderr => "")
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0,1]).and_return(chkconfig)
+ @provider.instance_variable_get("@service_missing").should be_false
+ @provider.load_current_resource
+ @current_resource.enabled.should be_true
+ end
+
+ it "sets the current enabled status to false if the regex does not match" do
+ status = mock("Status", :exitstatus => 0, :stdout => "" , :stderr => "")
+ @provider.should_receive(:shell_out).with("/sbin/service chef status").and_return(status)
+ chkconfig = mock("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:off 2:off 3:off 4:off 5:off 6:off", :stderr => "")
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0,1]).and_return(chkconfig)
+ @provider.instance_variable_get("@service_missing").should be_false
+ @provider.load_current_resource.should eql(@current_resource)
+ @current_resource.enabled.should be_false
+ end
+ end
+
+ describe "define resource requirements" do
+ it_should_behave_like "define_resource_requirements_common"
+
+ context "when the service does not exist" do
+ before do
+ status = mock("Status", :exitstatus => 1, :stdout => "", :stderr => "chef: unrecognized service")
+ @provider.should_receive(:shell_out).with("/sbin/service chef status").and_return(status)
+ chkconfig = mock("Chkconfig", :existatus=> 1, :stdout => "", :stderr => "error reading information on service chef: No such file or directory")
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0,1]).and_return(chkconfig)
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ end
+
+ [ "start", "reload", "restart", "enable" ].each do |action|
+ it "should raise an error when the action is #{action}" do
+ @provider.action = action
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ [ "stop", "disable" ].each do |action|
+ it "should not raise an error when the action is #{action}" do
+ @provider.action = action
+ lambda { @provider.process_resource_requirements }.should_not raise_error
+ end
+ end
+ end
+ end
+ end
+
+ describe "while in why run mode" do
+ before(:each) do
+ Chef::Config[:why_run] = true
+ end
+
+ after do
+ Chef::Config[:why_run] = false
+ end
+
+ describe "define resource requirements" do
+ it_should_behave_like "define_resource_requirements_common"
+
+ it "should not raise an error if the service does not exist" do
+ status = mock("Status", :exitstatus => 1, :stdout => "", :stderr => "chef: unrecognized service")
+ @provider.should_receive(:shell_out).with("/sbin/service chef status").and_return(status)
+ chkconfig = mock("Chkconfig", :existatus=> 1, :stdout => "", :stderr => "error reading information on service chef: No such file or directory")
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0,1]).and_return(chkconfig)
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should_not raise_error
+ end
+ end
+ end
+
+ describe "enable_service" do
+ it "should call chkconfig to add 'service_name'" do
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig #{@new_resource.service_name} on")
+ @provider.enable_service
+ end
+ end
+
+ describe "disable_service" do
+ it "should call chkconfig to del 'service_name'" do
+ @provider.should_receive(:shell_out!).with("/sbin/chkconfig #{@new_resource.service_name} off")
+ @provider.disable_service
+ end
+ end
+
+end
diff --git a/spec/unit/provider/service/simple_service_spec.rb b/spec/unit/provider/service/simple_service_spec.rb
new file mode 100644
index 0000000000..cc0173e246
--- /dev/null
+++ b/spec/unit/provider/service/simple_service_spec.rb
@@ -0,0 +1,171 @@
+#
+# Author:: Mathieu Sauve-Frankel <msf@kisoku.net>
+# Copyright:: Copyright (c) 2009, Mathieu Sauve Frankel
+# 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::Provider::Service::Simple, "load_current_resource" do
+ before(:each) do
+ @node = Chef::Node.new
+ @node.automatic_attrs[:command] = {:ps => "ps -ef"}
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("chef")
+ @current_resource = Chef::Resource::Service.new("chef")
+
+ @provider = Chef::Provider::Service::Simple.new(@new_resource, @run_context)
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+
+ @stdout = StringIO.new(<<-NOMOCKINGSTRINGSPLZ)
+aj 7842 5057 0 21:26 pts/2 00:00:06 vi init.rb
+aj 7903 5016 0 21:26 pts/5 00:00:00 /bin/bash
+aj 8119 6041 0 21:34 pts/3 00:00:03 vi simple_service_spec.rb
+NOMOCKINGSTRINGSPLZ
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ end
+
+ it "should create a current resource with the name of the new resource" do
+ Chef::Resource::Service.should_receive(:new).and_return(@current_resource)
+ @provider.load_current_resource
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @current_resource.should_receive(:service_name).with(@new_resource.service_name)
+ @provider.load_current_resource
+ end
+
+ it "should raise error if the node has a nil ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => nil}
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should raise error if the node has an empty ps attribute and no other means to get status" do
+ @node.automatic_attrs[:command] = {:ps => ""}
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ describe "when we have a 'ps' attribute" do
+ it "should shell_out! the node's ps command" do
+ @provider.should_receive(:shell_out!).with(@node[:command][:ps]).and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should read stdout of the ps command" do
+ @provider.stub!(:shell_out!).and_return(@status)
+ @stdout.should_receive(:each_line).and_return(true)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the regex matches the output" do
+ @stdout = StringIO.new(<<-NOMOCKINGSTRINGSPLZ)
+aj 7842 5057 0 21:26 pts/2 00:00:06 chef
+aj 7842 5057 0 21:26 pts/2 00:00:06 poos
+NOMOCKINGSTRINGSPLZ
+ @status = mock("Status", :exitstatus => 0, :stdout => @stdout)
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the regex doesn't match" do
+ @provider.stub!(:shell_out!).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+
+ it "should raise an exception if ps fails" do
+ @provider.stub!(:shell_out!).and_raise(Mixlib::ShellOut::ShellCommandFailed)
+ @provider.action = :start
+ @provider.load_current_resource
+ @provider.define_resource_requirements
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+
+
+
+ describe "when starting the service" do
+ it "should call the start command if one is specified" do
+ @new_resource.stub!(:start_command).and_return("#{@new_resource.start_command}")
+ @provider.should_receive(:shell_out!).with("#{@new_resource.start_command}")
+ @provider.start_service()
+ end
+
+ it "should raise an exception if no start command is specified" do
+ @provider.define_resource_requirements
+ @provider.action = :start
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ describe "when stopping a service" do
+ it "should call the stop command if one is specified" do
+ @new_resource.stop_command("/etc/init.d/themadness stop")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/themadness stop")
+ @provider.stop_service()
+ end
+
+ it "should raise an exception if no stop command is specified" do
+ @provider.define_resource_requirements
+ @provider.action = :stop
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+ end
+
+ describe Chef::Provider::Service::Simple, "restart_service" do
+ it "should call the restart command if one has been specified" do
+ @new_resource.restart_command("/etc/init.d/foo restart")
+ @provider.should_receive(:shell_out!).with("/etc/init.d/foo restart")
+ @provider.restart_service()
+ end
+
+ it "should raise an exception if the resource doesn't support restart, no restart command is provided, and no stop command is provided" do
+ @provider.define_resource_requirements
+ @provider.action = :restart
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ it "should just call stop, then start when the resource doesn't support restart and no restart_command is specified" do
+ @provider.should_receive(:stop_service)
+ @provider.should_receive(:sleep).with(1)
+ @provider.should_receive(:start_service)
+ @provider.restart_service()
+ end
+ end
+
+ describe Chef::Provider::Service::Simple, "reload_service" do
+ it "should raise an exception if reload is requested but no command is specified" do
+ @provider.define_resource_requirements
+ @provider.action = :reload
+ lambda { @provider.process_resource_requirements }.should raise_error(Chef::Exceptions::UnsupportedAction)
+ end
+
+ it "should should run the user specified reload command if one is specified" do
+ @new_resource.reload_command("kill -9 1")
+ @provider.should_receive(:shell_out!).with("kill -9 1")
+ @provider.reload_service()
+ end
+ end
+end
diff --git a/spec/unit/provider/service/solaris_smf_service_spec.rb b/spec/unit/provider/service/solaris_smf_service_spec.rb
new file mode 100644
index 0000000000..3ea2902755
--- /dev/null
+++ b/spec/unit/provider/service/solaris_smf_service_spec.rb
@@ -0,0 +1,140 @@
+#
+# Author:: Toomas Pelberg (<toomasp@gmx.net>)
+# Copyright:: Copyright (c) 2010 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::Provider::Service::Solaris do
+ before(:each) do
+ @node =Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new('chef')
+
+ @current_resource = Chef::Resource::Service.new('chef')
+
+ @provider = Chef::Provider::Service::Solaris.new(@new_resource, @run_context)
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+
+ @stdin = StringIO.new
+ @stdout = StringIO.new
+ @stderr = StringIO.new
+ @pid = 2342
+ @stdout_string = "state disabled"
+ @stdout.stub!(:gets).and_return(@stdout_string)
+ end
+
+ it "should raise an error if /bin/svcs does not exist" do
+ File.should_receive(:exists?).with("/bin/svcs").and_return(false)
+ lambda { @provider.load_current_resource }.should raise_error(Chef::Exceptions::Service)
+ end
+
+ describe "on a host with /bin/svcs" do
+
+ before do
+ File.stub!(:exists?).with('/bin/svcs').and_return(true)
+ end
+
+ describe "when discovering the current service state" do
+ it "should create a current resource with the name of the new resource" do
+ @provider.stub!(:popen4).with("/bin/svcs -l chef").and_return(@status)
+ Chef::Resource::Service.should_receive(:new).and_return(@current_resource)
+ @provider.load_current_resource
+ end
+
+
+ it "should return the current resource" do
+ @provider.stub!(:popen4).with("/bin/svcs -l chef").and_return(@status)
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+
+ it "should popen4 '/bin/svcs -l service_name'" do
+ @provider.should_receive(:popen4).with("/bin/svcs -l chef").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ it "should mark service as not running" do
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+ it "should mark service as running" do
+ @stdout.stub!(:each).and_yield("state online")
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @current_resource.should_receive(:running).with(true)
+ @provider.load_current_resource
+ end
+ end
+
+ describe "when enabling the service" do
+ before(:each) do
+ #@provider = Chef::Provider::Service::Solaris.new(@node, @new_resource)
+ @provider.current_resource = @current_resource
+ @current_resource.enabled(true)
+ end
+
+ it "should call svcadm enable chef" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/svcadm enable chef"})
+ @provider.should_receive(:service_status).and_return(@current_resource)
+ @provider.enable_service.should be_true
+ end
+
+ it "should call svcadm enable chef for start_service" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/svcadm enable chef"})
+ @provider.should_receive(:service_status).and_return(@current_resource)
+ @provider.start_service.should be_true
+ end
+
+ end
+
+
+ describe "when disabling the service" do
+ before(:each) do
+ @provider.current_resource = @current_resource
+ @current_resource.enabled(false)
+ end
+
+ it "should call svcadm disable chef" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/svcadm disable chef"})
+ @provider.should_receive(:service_status).and_return(@current_resource)
+ @provider.disable_service.should be_false
+ end
+
+ it "should call svcadm disable chef for stop_service" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/svcadm disable chef"})
+ @provider.should_receive(:service_status).and_return(@current_resource)
+ @provider.stop_service.should be_false
+ end
+
+ end
+
+ describe "when reloading the service" do
+ before(:each) do
+ @status = mock("Process::Status", :exitstatus => 0)
+ @provider.current_resource = @current_resource
+ end
+
+ it "should call svcadm refresh chef" do
+ @provider.should_receive(:run_command).with({:command => "/usr/sbin/svcadm refresh chef"}).and_return(@status)
+ @provider.reload_service.should be_true
+ end
+
+ end
+ end
+end
diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb
new file mode 100644
index 0000000000..dbdedecd40
--- /dev/null
+++ b/spec/unit/provider/service/systemd_service_spec.rb
@@ -0,0 +1,239 @@
+#
+# Author:: Stephen Haynes (<sh@nomitor.com>)
+# Copyright:: Copyright (c) 2011 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::Provider::Service::Systemd do
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+ @new_resource = Chef::Resource::Service.new('rsyslog.service')
+ @provider = Chef::Provider::Service::Systemd.new(@new_resource, @run_context)
+ end
+
+ describe "load_current_resource" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog.service')
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+
+ @provider.stub!(:is_active?).and_return(false)
+ @provider.stub!(:is_enabled?).and_return(false)
+ end
+
+ it "should create a current resource with the name of the new resource" do
+ Chef::Resource::Service.should_receive(:new).and_return(@current_resource)
+ @provider.load_current_resource
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @current_resource.should_receive(:service_name).with(@new_resource.service_name)
+ @provider.load_current_resource
+ end
+
+ it "should check if the service is running" do
+ @provider.should_receive(:is_active?)
+ @provider.load_current_resource
+ end
+
+ it "should set running to true if the service is running" do
+ @provider.stub!(:is_active?).and_return(true)
+ @current_resource.should_receive(:running).with(true)
+ @provider.load_current_resource
+ end
+
+ it "should set running to false if the service is not running" do
+ @provider.stub!(:is_active?).and_return(false)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+ describe "when a status command has been specified" do
+ before do
+ @new_resource.stub!(:status_command).and_return("/bin/chefhasmonkeypants status")
+ end
+
+ it "should run the services status command if one has been specified" do
+ @provider.stub!(:run_command_with_systems_locale).with({:command => "/bin/chefhasmonkeypants status"}).and_return(0)
+ @current_resource.should_receive(:running).with(true)
+ @provider.load_current_resource
+ end
+
+ it "should run the services status command if one has been specified and properly set status check state" do
+ @provider.stub!(:run_command_with_systems_locale).with({:command => "/bin/chefhasmonkeypants status"}).and_return(0)
+ @provider.load_current_resource
+ @provider.instance_variable_get("@status_check_success").should be_true
+ end
+
+ it "should set running to false if it catches a Chef::Exceptions::Exec when using a status command" do
+ @provider.stub!(:run_command_with_systems_locale).and_raise(Chef::Exceptions::Exec)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+ it "should update state to indicate status check failed when an exception is thrown using a status command" do
+ @provider.stub!(:run_command_with_systems_locale).and_raise(Chef::Exceptions::Exec)
+ @provider.load_current_resource
+ @provider.instance_variable_get("@status_check_success").should be_false
+ end
+ end
+
+ it "should check if the service is enabled" do
+ @provider.should_receive(:is_enabled?)
+ @provider.load_current_resource
+ end
+
+ it "should set enabled to true if the service is enabled" do
+ @provider.stub!(:is_enabled?).and_return(true)
+ @current_resource.should_receive(:enabled).with(true)
+ @provider.load_current_resource
+ end
+
+ it "should set enabled to false if the service is not enabled" do
+ @provider.stub!(:is_enabled?).and_return(false)
+ @current_resource.should_receive(:enabled).with(false)
+ @provider.load_current_resource
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+ end
+
+ describe "start and stop service" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog.service')
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.current_resource = @current_resource
+ end
+
+ it "should call the start command if one is specified" do
+ @new_resource.stub!(:start_command).and_return("/sbin/rsyslog startyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog startyousillysally")
+ @provider.start_service
+ end
+
+ it "should call '/bin/systemctl start service_name' if no start command is specified" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl start #{@new_resource.service_name}"}).and_return(0)
+ @provider.start_service
+ end
+
+ it "should not call '/bin/systemctl start service_name' if it is already running" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_not_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl start #{@new_resource.service_name}"}).and_return(0)
+ @provider.start_service
+ end
+
+ it "should call the restart command if one is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @new_resource.stub!(:restart_command).and_return("/sbin/rsyslog restartyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog restartyousillysally")
+ @provider.restart_service
+ end
+
+ it "should call '/bin/systemctl restart service_name' if no restart command is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl restart #{@new_resource.service_name}"}).and_return(0)
+ @provider.restart_service
+ end
+
+ it "should call the reload command if one is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @new_resource.stub!(:reload_command).and_return("/sbin/rsyslog reloadyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog reloadyousillysally")
+ @provider.reload_service
+ end
+
+ it "should call '/bin/systemctl reload service_name' if no reload command is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl reload #{@new_resource.service_name}"}).and_return(0)
+ @provider.reload_service
+ end
+
+ it "should call the stop command if one is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @new_resource.stub!(:stop_command).and_return("/sbin/rsyslog stopyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog stopyousillysally")
+ @provider.stop_service
+ end
+
+ it "should call '/bin/systemctl stop service_name' if no stop command is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl stop #{@new_resource.service_name}"}).and_return(0)
+ @provider.stop_service
+ end
+
+ it "should not call '/bin/systemctl stop service_name' if it is already stopped" do
+ @current_resource.stub!(:running).and_return(false)
+ @provider.should_not_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl stop #{@new_resource.service_name}"}).and_return(0)
+ @provider.stop_service
+ end
+ end
+
+ describe "enable and disable service" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog.service')
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.current_resource = @current_resource
+ end
+
+ it "should call '/bin/systemctl enable service_name' to enable the service" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl enable #{@new_resource.service_name}"}).and_return(0)
+ @provider.enable_service
+ end
+
+ it "should call '/bin/systemctl disable service_name' to disable the service" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/bin/systemctl disable #{@new_resource.service_name}"}).and_return(0)
+ @provider.disable_service
+ end
+ end
+
+ describe "is_active?" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog.service')
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ end
+
+ it "should return true if '/bin/systemctl is-active service_name' returns 0" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => '/bin/systemctl is-active rsyslog.service', :ignore_failure => true}).and_return(0)
+ @provider.is_active?.should be_true
+ end
+
+ it "should return false if '/bin/systemctl is-active service_name' returns anything except 0" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => '/bin/systemctl is-active rsyslog.service', :ignore_failure => true}).and_return(1)
+ @provider.is_active?.should be_false
+ end
+ end
+
+ describe "is_enabled?" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog.service')
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ end
+
+ it "should return true if '/bin/systemctl is-enabled service_name' returns 0" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => '/bin/systemctl is-enabled rsyslog.service', :ignore_failure => true}).and_return(0)
+ @provider.is_enabled?.should be_true
+ end
+
+ it "should return false if '/bin/systemctl is-enabled service_name' returns anything except 0" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => '/bin/systemctl is-enabled rsyslog.service', :ignore_failure => true}).and_return(1)
+ @provider.is_enabled?.should be_false
+ end
+ end
+end
diff --git a/spec/unit/provider/service/upstart_service_spec.rb b/spec/unit/provider/service/upstart_service_spec.rb
new file mode 100644
index 0000000000..2fc49c7aa2
--- /dev/null
+++ b/spec/unit/provider/service/upstart_service_spec.rb
@@ -0,0 +1,314 @@
+#
+# Author:: Bryan McLellan (btm@loftninjas.org)
+# Copyright:: Copyright (c) 2010 Bryan McLellan
+# 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::Provider::Service::Upstart do
+ before(:each) do
+ @node =Chef::Node.new
+ @node.name('upstarter')
+ @node.automatic_attrs[:platform] = 'ubuntu'
+ @node.automatic_attrs[:platform_version] = '9.10'
+
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+
+ @new_resource = Chef::Resource::Service.new("rsyslog")
+ @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context)
+ end
+
+ describe "when first created" do
+ before do
+ @platform = nil
+ end
+
+ it "should return /etc/event.d as the upstart job directory when running on Ubuntu 9.04" do
+ @node.automatic_attrs[:platform_version] = '9.04'
+ #Chef::Platform.stub!(:find_platform_and_version).and_return([ "ubuntu", "9.04" ])
+ @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context)
+ @provider.instance_variable_get(:@upstart_job_dir).should == "/etc/event.d"
+ @provider.instance_variable_get(:@upstart_conf_suffix).should == ""
+ end
+
+ it "should return /etc/init as the upstart job directory when running on Ubuntu 9.10" do
+ @node.automatic_attrs[:platform_version] = '9.10'
+ @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context)
+ @provider.instance_variable_get(:@upstart_job_dir).should == "/etc/init"
+ @provider.instance_variable_get(:@upstart_conf_suffix).should == ".conf"
+ end
+
+ it "should return /etc/init as the upstart job directory by default" do
+ @node.automatic_attrs[:platform_version] = '9000'
+ @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context)
+ @provider.instance_variable_get(:@upstart_job_dir).should == "/etc/init"
+ @provider.instance_variable_get(:@upstart_conf_suffix).should == ".conf"
+ end
+ end
+
+ describe "load_current_resource" do
+ before(:each) do
+ @node.automatic_attrs[:command] = {:ps => "ps -ax"}
+
+ @current_resource = Chef::Resource::Service.new("rsyslog")
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+
+ @status = mock("Status", :exitstatus => 0)
+ @provider.stub!(:popen4).and_return(@status)
+ @stdin = StringIO.new
+ @stdout = StringIO.new
+ @stderr = StringIO.new
+ @pid = mock("PID")
+
+ ::File.stub!(:exists?).and_return(true)
+ ::File.stub!(:open).and_return(true)
+ end
+
+ it "should create a current resource with the name of the new resource" do
+ Chef::Resource::Service.should_receive(:new).and_return(@current_resource)
+ @provider.load_current_resource
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @current_resource.should_receive(:service_name).with(@new_resource.service_name)
+ @provider.load_current_resource
+ end
+
+ it "should run '/sbin/status rsyslog'" do
+ @provider.should_receive(:popen4).with("/sbin/status rsyslog").and_return(@status)
+ @provider.load_current_resource
+ end
+
+ describe "when the status command uses the new format" do
+ before do
+ end
+
+ it "should set running to true if the the status command returns 0" do
+ @stdout = StringIO.new("rsyslog start/running")
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the status command returns anything except 0" do
+ @stdout = StringIO.new("rsyslog stop/waiting")
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+ end
+
+ describe "when the status command uses the old format" do
+ it "should set running to true if the the status command returns 0" do
+ @stdout = StringIO.new("rsyslog (start) running, process 32225")
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_true
+ end
+
+ it "should set running to false if the status command returns anything except 0" do
+ @stdout = StringIO.new("rsyslog (stop) waiting")
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @provider.load_current_resource
+ @current_resource.running.should be_false
+ end
+ end
+
+ it "should set running to false if it catches a Chef::Exceptions::Exec" do
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_raise(Chef::Exceptions::Exec)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+ it "should set enabled to true when it finds 'starts on'" do
+ @lines = mock("start on filesystem", :gets => "start on filesystem")
+ ::File.stub!(:open).and_yield(@lines)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+ it "should set enabled to false when it finds '#starts on'" do
+ @lines = mock("start on filesystem", :gets => "#start on filesystem")
+ ::File.stub!(:open).and_yield(@lines)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+ it "should assume disable when no job configuration file is found" do
+ ::File.stub!(:exists?).and_return(false)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+
+
+ it "should track state when the upstart configuration file fails to load" do
+ File.should_receive(:exists?).and_return false
+ @provider.load_current_resource
+ @provider.instance_variable_get("@config_file_found").should == false
+ end
+
+ describe "when a status command has been specified" do
+ before do
+ @new_resource.stub!(:status_command).and_return("/bin/chefhasmonkeypants status")
+ end
+
+ it "should run the services status command if one has been specified" do
+ @provider.stub!(:run_command_with_systems_locale).with({:command => "/bin/chefhasmonkeypants status"}).and_return(0)
+ @current_resource.should_receive(:running).with(true)
+ @provider.load_current_resource
+ end
+
+ it "should track state when the user-provided status command fails" do
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_raise(Chef::Exceptions::Exec)
+ @provider.load_current_resource
+ @provider.instance_variable_get("@command_success").should == false
+ end
+
+ it "should set running to false if it catches a Chef::Exceptions::Exec when using a status command" do
+ @provider.stub!(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_raise(Chef::Exceptions::Exec)
+ @current_resource.should_receive(:running).with(false)
+ @provider.load_current_resource
+ end
+ end
+
+ it "should track state when we fail to obtain service status via upstart_state" do
+ @provider.should_receive(:upstart_state).and_raise Chef::Exceptions::Exec
+ @provider.load_current_resource
+ @provider.instance_variable_get("@command_success").should == false
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should eql(@current_resource)
+ end
+
+
+ end
+
+ describe "enable and disable service" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog')
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.current_resource = @current_resource
+ Chef::Util::FileEdit.stub!(:new)
+ end
+
+ it "should enable the service if it is not enabled" do
+ @file = Object.new
+ Chef::Util::FileEdit.stub!(:new).and_return(@file)
+ @current_resource.stub!(:enabled).and_return(false)
+ @file.should_receive(:search_file_replace)
+ @file.should_receive(:write_file)
+ @provider.enable_service()
+ end
+
+ it "should disable the service if it is enabled" do
+ @file = Object.new
+ Chef::Util::FileEdit.stub!(:new).and_return(@file)
+ @current_resource.stub!(:enabled).and_return(true)
+ @file.should_receive(:search_file_replace)
+ @file.should_receive(:write_file)
+ @provider.disable_service()
+ end
+
+ end
+
+ describe "start and stop service" do
+ before(:each) do
+ @current_resource = Chef::Resource::Service.new('rsyslog')
+
+ Chef::Resource::Service.stub!(:new).and_return(@current_resource)
+ @provider.current_resource = @current_resource
+ end
+
+ it "should call the start command if one is specified" do
+ @new_resource.stub!(:start_command).and_return("/sbin/rsyslog startyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog startyousillysally")
+ @provider.start_service()
+ end
+
+ it "should call '/sbin/start service_name' if no start command is specified" do
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/sbin/start #{@new_resource.service_name}"}).and_return(0)
+ @provider.start_service()
+ end
+
+ it "should not call '/sbin/start service_name' if it is already running" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_not_receive(:run_command_with_systems_locale).with({:command => "/sbin/start #{@new_resource.service_name}"}).and_return(0)
+ @provider.start_service()
+ end
+
+ it "should pass parameters to the start command if they are provided" do
+ @new_resource = Chef::Resource::Service.new("rsyslog")
+ @new_resource.parameters({ "OSD_ID" => "2" })
+ @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context)
+ @provider.current_resource = @current_resource
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/sbin/start rsyslog OSD_ID=2"}).and_return(0)
+ @provider.start_service()
+ end
+
+ it "should call the restart command if one is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @new_resource.stub!(:restart_command).and_return("/sbin/rsyslog restartyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog restartyousillysally")
+ @provider.restart_service()
+ end
+
+ it "should call '/sbin/restart service_name' if no restart command is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/sbin/restart #{@new_resource.service_name}"}).and_return(0)
+ @provider.restart_service()
+ end
+
+ it "should call '/sbin/start service_name' if restart_service is called for a stopped service" do
+ @current_resource.stub!(:running).and_return(false)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/sbin/start #{@new_resource.service_name}"}).and_return(0)
+ @provider.restart_service()
+ end
+
+ it "should call the reload command if one is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @new_resource.stub!(:reload_command).and_return("/sbin/rsyslog reloadyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog reloadyousillysally")
+ @provider.reload_service()
+ end
+
+ it "should call '/sbin/reload service_name' if no reload command is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/sbin/reload #{@new_resource.service_name}"}).and_return(0)
+ @provider.reload_service()
+ end
+
+ it "should call the stop command if one is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @new_resource.stub!(:stop_command).and_return("/sbin/rsyslog stopyousillysally")
+ @provider.should_receive(:shell_out!).with("/sbin/rsyslog stopyousillysally")
+ @provider.stop_service()
+ end
+
+ it "should call '/sbin/stop service_name' if no stop command is specified" do
+ @current_resource.stub!(:running).and_return(true)
+ @provider.should_receive(:run_command_with_systems_locale).with({:command => "/sbin/stop #{@new_resource.service_name}"}).and_return(0)
+ @provider.stop_service()
+ end
+
+ it "should not call '/sbin/stop service_name' if it is already stopped" do
+ @current_resource.stub!(:running).and_return(false)
+ @provider.should_not_receive(:run_command_with_systems_locale).with({:command => "/sbin/stop #{@new_resource.service_name}"}).and_return(0)
+ @provider.stop_service()
+ end
+ end
+end
diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb
new file mode 100644
index 0000000000..a68e798d36
--- /dev/null
+++ b/spec/unit/provider/service/windows_spec.rb
@@ -0,0 +1,235 @@
+#
+# Author:: Nuo Yan <nuo@opscode.com>
+# Author:: Seth Chisamore <schisamo@opscode.com>
+# Copyright:: Copyright (c) 2010-2011 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::Provider::Service::Windows, "load_current_resource" do
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+ @new_resource = Chef::Resource::Service.new("chef")
+ @provider = Chef::Provider::Service::Windows.new(@new_resource, @run_context)
+ Object.send(:remove_const, 'Win32') if defined?(Win32)
+ Win32 = Module.new
+ Win32::Service = Class.new
+ Win32::Service::AUTO_START = 0x00000002
+ Win32::Service::DISABLED = 0x00000004
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "running"))
+ Win32::Service.stub!(:config_info).with(@new_resource.service_name).and_return(
+ mock("ConfigStruct", :start_type => "auto start"))
+ Win32::Service.stub!(:exists?).and_return(true)
+ end
+
+ it "should set the current resources service name to the new resources service name" do
+ @provider.load_current_resource
+ @provider.current_resource.service_name.should == 'chef'
+ end
+
+ it "should return the current resource" do
+ @provider.load_current_resource.should equal(@provider.current_resource)
+ end
+
+ it "should set the current resources status" do
+ @provider.load_current_resource
+ @provider.current_resource.running.should be_true
+ end
+
+ it "should set the current resources start type" do
+ @provider.load_current_resource
+ @provider.current_resource.enabled.should be_true
+ end
+
+ describe Chef::Provider::Service::Windows, "start_service" do
+ before(:each) do
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "stopped"),
+ mock("StatusStruct", :current_state => "running"))
+ end
+
+ it "should call the start command if one is specified" do
+ @new_resource.start_command "sc start chef"
+ @provider.should_receive(:shell_out!).with("#{@new_resource.start_command}").and_return("Starting custom service")
+ @provider.start_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should use the built-in command if no start command is specified" do
+ Win32::Service.should_receive(:start).with(@new_resource.service_name)
+ @provider.start_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should do nothing if the service does not exist" do
+ Win32::Service.stub!(:exists?).with(@new_resource.service_name).and_return(false)
+ Win32::Service.should_not_receive(:start).with(@new_resource.service_name)
+ @provider.start_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+
+ it "should do nothing if the service is running" do
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "running"))
+ @provider.load_current_resource
+ Win32::Service.should_not_receive(:start).with(@new_resource.service_name)
+ @provider.start_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "stop_service" do
+
+ before(:each) do
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "running"),
+ mock("StatusStruct", :current_state => "stopped"))
+ end
+
+ it "should call the stop command if one is specified" do
+ @new_resource.stop_command "sc stop chef"
+ @provider.should_receive(:shell_out!).with("#{@new_resource.stop_command}").and_return("Stopping custom service")
+ @provider.stop_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should use the built-in command if no stop command is specified" do
+ Win32::Service.should_receive(:stop).with(@new_resource.service_name)
+ @provider.stop_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should do nothing if the service does not exist" do
+ Win32::Service.stub!(:exists?).with(@new_resource.service_name).and_return(false)
+ Win32::Service.should_not_receive(:stop).with(@new_resource.service_name)
+ @provider.stop_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+
+ it "should do nothing if the service is stopped" do
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "stopped"))
+ @provider.load_current_resource
+ Win32::Service.should_not_receive(:stop).with(@new_resource.service_name)
+ @provider.stop_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "restart_service" do
+
+ it "should call the restart command if one is specified" do
+ @new_resource.restart_command "sc restart"
+ @provider.should_receive(:shell_out!).with("#{@new_resource.restart_command}")
+ @provider.restart_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should stop then start the service if it is running" do
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "running"),
+ mock("StatusStruct", :current_state => "stopped"),
+ mock("StatusStruct", :current_state => "stopped"),
+ mock("StatusStruct", :current_state => "running"))
+ Win32::Service.should_receive(:stop).with(@new_resource.service_name)
+ Win32::Service.should_receive(:start).with(@new_resource.service_name)
+ @provider.restart_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should just start the service if it is stopped" do
+ Win32::Service.stub!(:status).with(@new_resource.service_name).and_return(
+ mock("StatusStruct", :current_state => "stopped"),
+ mock("StatusStruct", :current_state => "stopped"),
+ mock("StatusStruct", :current_state => "running"))
+ Win32::Service.should_receive(:start).with(@new_resource.service_name)
+ @provider.restart_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should do nothing if the service does not exist" do
+ Win32::Service.stub!(:exists?).with(@new_resource.service_name).and_return(false)
+ Win32::Service.should_not_receive(:stop).with(@new_resource.service_name)
+ Win32::Service.should_not_receive(:start).with(@new_resource.service_name)
+ @provider.restart_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+
+ end
+
+ describe Chef::Provider::Service::Windows, "enable_service" do
+
+ before(:each) do
+ Win32::Service.stub!(:config_info).with(@new_resource.service_name).and_return(
+ mock("ConfigStruct", :start_type => "disabled"))
+ end
+
+ it "should enable service" do
+ Win32::Service.should_receive(:configure).with(:service_name => @new_resource.service_name, :start_type => Win32::Service::AUTO_START)
+ @provider.enable_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should do nothing if the service does not exist" do
+ Win32::Service.stub!(:exists?).with(@new_resource.service_name).and_return(false)
+ Win32::Service.should_not_receive(:configure)
+ @provider.enable_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+
+ it "should do nothing if the service is enabled" do
+ Win32::Service.stub!(:config_info).with(@new_resource.service_name).and_return(
+ mock("ConfigStruct", :start_type => "auto start"))
+ Win32::Service.should_not_receive(:configure)
+ @provider.enable_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "disable_service" do
+
+ before(:each) do
+ Win32::Service.stub!(:config_info).with(@new_resource.service_name).and_return(
+ mock("ConfigStruct", :start_type => "auto start"))
+ end
+
+ it "should disable service" do
+ Win32::Service.should_receive(:configure).with(:service_name => @new_resource.service_name, :start_type => Win32::Service::DISABLED)
+ @provider.disable_service
+ @new_resource.updated_by_last_action?.should be_true
+ end
+
+ it "should do nothing if the service does not exist" do
+ Win32::Service.stub!(:exists?).with(@new_resource.service_name).and_return(false)
+ Win32::Service.should_not_receive(:configure)
+ @provider.disable_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+
+ it "should do nothing if the service is disabled" do
+ Win32::Service.stub!(:config_info).with(@new_resource.service_name).and_return(
+ mock("ConfigStruct", :start_type => "disabled"))
+ @provider.load_current_resource
+ Win32::Service.should_not_receive(:configure)
+ @provider.disable_service
+ @new_resource.updated_by_last_action?.should be_false
+ end
+
+ end
+end