diff options
-rw-r--r-- | lib/chef/provider/service/solaris.rb | 60 | ||||
-rw-r--r-- | spec/unit/provider/service/solaris_smf_service_spec.rb | 149 |
2 files changed, 153 insertions, 56 deletions
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb index eaea6bb1ab..7040503c6b 100644 --- a/lib/chef/provider/service/solaris.rb +++ b/lib/chef/provider/service/solaris.rb @@ -30,35 +30,39 @@ class Chef def initialize(new_resource, run_context=nil) super - @init_command = "/usr/sbin/svcadm" - @status_command = "/bin/svcs -l" + @init_command = "/usr/sbin/svcadm" + @status_command = "/bin/svcs" @maintenace = false end def load_current_resource @current_resource = Chef::Resource::Service.new(@new_resource.name) @current_resource.service_name(@new_resource.service_name) - unless ::File.exists? "/bin/svcs" - raise Chef::Exceptions::Service, "/bin/svcs does not exist!" + + [@init_command, @status_command].each do |cmd| + unless ::File.executable? cmd then + raise Chef::Exceptions::Service, "#{cmd} not executable!" + end end @status = service_status.enabled + @current_resource end def enable_service - shell_out!("#{default_init_command} clear #{@new_resource.service_name}") if @maintenance - shell_out!("#{default_init_command} enable -s #{@new_resource.service_name}") + shell_out!(default_init_command, "clear", @new_resource.service_name) if @maintenance + shell_out!(default_init_command, "enable", "-s", @new_resource.service_name) end def disable_service - shell_out!("#{default_init_command} disable -s #{@new_resource.service_name}") + shell_out!(default_init_command, "disable", "-s", @new_resource.service_name) end alias_method :stop_service, :disable_service alias_method :start_service, :enable_service def reload_service - shell_out_with_systems_locale!("#{default_init_command} refresh #{@new_resource.service_name}") + shell_out!(default_init_command, "refresh", @new_resource.service_name) end def restart_service @@ -68,16 +72,38 @@ class Chef end def service_status - status = shell_out!("#{@status_command} #{@current_resource.service_name}", :returns => [0, 1]) - status.stdout.each_line do |line| - case line - when /state\s+online/ - @current_resource.enabled(true) - @current_resource.running(true) - when /state\s+maintenance/ - @maintenance = true - end + cmd = shell_out!(@status_command, "-l", @current_resource.service_name, :returns => [0, 1]) + # Example output + # $ svcs -l rsyslog + # fmri svc:/application/rsyslog:default + # name rsyslog logging utility + # enabled true + # state online + # next_state none + # state_time April 2, 2015 04:25:19 PM EDT + # logfile /var/svc/log/application-rsyslog:default.log + # restarter svc:/system/svc/restarter:default + # contract_id 1115271 + # dependency require_all/error svc:/milestone/multi-user:default (online) + # $ + + # load output into hash + status = {} + cmd.stdout.each_line do |line| + key, value = line.strip.split(/\s+/, 2) + status[key] = value + end + + # check service state + @maintenance = false + case status['state'] + when 'online' + @current_resource.enabled(true) + @current_resource.running(true) + when 'maintenance' + @maintenance = true end + unless @current_resource.enabled @current_resource.enabled(false) @current_resource.running(false) diff --git a/spec/unit/provider/service/solaris_smf_service_spec.rb b/spec/unit/provider/service/solaris_smf_service_spec.rb index 2039408914..62c3ac6c6e 100644 --- a/spec/unit/provider/service/solaris_smf_service_spec.rb +++ b/spec/unit/provider/service/solaris_smf_service_spec.rb @@ -31,66 +31,126 @@ describe Chef::Provider::Service::Solaris do @provider = Chef::Provider::Service::Solaris.new(@new_resource, @run_context) allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource) - @stdin = StringIO.new - @stdout = StringIO.new - @stderr = StringIO.new - @pid = 2342 - @stdout_string = "state disabled" - allow(@stdout).to receive(:gets).and_return(@stdout_string) - @status = double("Status", :exitstatus => 0, :stdout => @stdout) - allow(@provider).to receive(:shell_out!).and_return(@status) + # enabled / started service (svcs -l chef) + enabled_svc_stdout = [ + 'fmri svc:/application/chef:default', + 'name chef service', + 'enabled true', + 'state online', + 'next_state none', + 'state_time April 2, 2015 04:25:19 PM EDT', + 'logfile /var/svc/log/application-chef:default.log', + 'restarter svc:/system/svc/restarter:default', + 'contract_id 1115271', + 'dependency require_all/error svc:/milestone/multi-user:default (online)' + ].join("\n") + + # disabled / stopped service (svcs -l chef) + disabled_svc_stdout = [ + 'fmri svc:/application/chef:default', + 'name chef service', + 'enabled false', + 'state disabled', + 'next_state none', + 'state_time April 2, 2015 04:25:19 PM EDT', + 'logfile /var/svc/log/application-chef:default.log', + 'restarter svc:/system/svc/restarter:default', + 'contract_id 1115271', + 'dependency require_all/error svc:/milestone/multi-user:default (online)' + ].join("\n") + + # disabled / stopped service (svcs -l chef) + maintenance_svc_stdout = [ + 'fmri svc:/application/chef:default', + 'name chef service', + 'enabled true', + 'state maintenance', + 'next_state none', + 'state_time April 2, 2015 04:25:19 PM EDT', + 'logfile /var/svc/log/application-chef:default.log', + 'restarter svc:/system/svc/restarter:default', + 'contract_id 1115271', + 'dependency require_all/error svc:/milestone/multi-user:default (online)' + ].join("\n") + + # shell_out! return value for a service that is running + @enabled_svc_status = double("Status", :exitstatus => 0, :stdout => enabled_svc_stdout, :stdin => '', :stderr => '') + + # shell_out! return value for a service that is disabled + @disabled_svc_status = double("Status", :exitstatus => 0, :stdout => disabled_svc_stdout, :stdin => '', :stderr => '') + + # shell_out! return value for a service that is in maintenance mode + @maintenance_svc_status = double("Status", :exitstatus => 0, :stdout => maintenance_svc_stdout, :stdin => '', :stderr => '') + + # shell_out! return value for a service that does not exist + @no_svc_status = double("Status", :exitstatus => 1, :stdout => '', :stdin => '', :stderr => "svcs: Pattern 'chef' doesn't match any instances\n") + + # shell_out! return value for a successful execution + @success = double("clear", :exitstatus => 0, :stdout => '', :stdin => '', :stderr => '') end - it "should raise an error if /bin/svcs does not exist" do - expect(File).to receive(:exists?).with("/bin/svcs").and_return(false) + it "should raise an error if /bin/svcs and /usr/sbin/svcadm are not executable" do + allow(File).to receive(:executable?).with("/bin/svcs").and_return(false) + allow(File).to receive(:executable?).with("/usr/sbin/svcadm").and_return(false) expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Service) end - describe "on a host with /bin/svcs" do + it "should raise an error if /bin/svcs is not executable" do + allow(File).to receive(:executable?).with("/bin/svcs").and_return(false) + allow(File).to receive(:executable?).with("/usr/sbin/svcadm").and_return(true) + expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Service) + end + + it "should raise an error if /usr/sbin/svcadm is not executable" do + allow(File).to receive(:executable?).with("/bin/svcs").and_return(true) + allow(File).to receive(:executable?).with("/usr/sbin/svcadm").and_return(false) + expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Service) + end + + describe "on a host with /bin/svcs and /usr/sbin/svcadm" do before do - allow(File).to receive(:exists?).with('/bin/svcs').and_return(true) + allow(File).to receive(:executable?).with("/bin/svcs").and_return(true) + allow(File).to receive(:executable?).with("/usr/sbin/svcadm").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 - allow(@provider).to receive(:shell_out!).with("/bin/svcs -l chef").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) expect(Chef::Resource::Service).to receive(:new).and_return(@current_resource) @provider.load_current_resource end it "should return the current resource" do - allow(@provider).to receive(:shell_out!).with("/bin/svcs -l chef").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) expect(@provider.load_current_resource).to eql(@current_resource) end it "should call '/bin/svcs -l service_name'" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs -l chef", {:returns=>[0, 1]}).and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) @provider.load_current_resource end it "should mark service as not running" do - allow(@provider).to receive(:shell_out!).and_return(@status) + expect(@provider).to receive(:shell_out!).and_return(@disabled_svc_status) expect(@current_resource).to receive(:running).with(false) @provider.load_current_resource end it "should mark service as running" do - @status = double("Status", :exitstatus => 0, :stdout => 'state online') - allow(@provider).to receive(:shell_out!).and_return(@status) + expect(@provider).to receive(:shell_out!).and_return(@enabled_svc_status) expect(@current_resource).to receive(:running).with(true) @provider.load_current_resource end it "should not mark service as maintenance" do - allow(@provider).to receive(:shell_out!).and_return(@status) + expect(@provider).to receive(:shell_out!).and_return(@enabled_svc_status) @provider.load_current_resource expect(@provider.maintenance).to be_falsey end it "should mark service as maintenance" do - @status = double("Status", :exitstatus => 0, :stdout => 'state maintenance') - allow(@provider).to receive(:shell_out!).and_return(@status) + expect(@provider).to receive(:shell_out!).and_return(@maintenance_svc_status) @provider.load_current_resource expect(@provider.maintenance).to be_truthy end @@ -99,30 +159,41 @@ describe Chef::Provider::Service::Solaris do describe "when enabling the service" do before(:each) do @provider.current_resource = @current_resource - @current_resource.enabled(true) end it "should call svcadm enable -s chef" do - expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm clear #{@current_resource.service_name}") - expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm enable -s #{@current_resource.service_name}").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) + expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", @current_resource.service_name).and_return(@success) + @provider.load_current_resource + expect(@provider.enable_service).to be_truthy expect(@current_resource.enabled).to be_truthy end it "should call svcadm enable -s chef for start_service" do - expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm clear #{@current_resource.service_name}") - expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm enable -s #{@current_resource.service_name}").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) + expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", @current_resource.service_name).and_return(@success) + @provider.load_current_resource expect(@provider.start_service).to be_truthy expect(@current_resource.enabled).to be_truthy end it "should call svcadm clear chef for start_service when state maintenance" do - @status = double("Status", :exitstatus => 0, :stdout => 'state maintenance') - allow(@provider).to receive(:shell_out!).and_return(@status) + # we are in maint mode + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@maintenance_svc_status) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name).and_return(@success) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", @current_resource.service_name).and_return(@success) + + # load the resource, then enable it @provider.load_current_resource - expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm clear #{@current_resource.service_name}").and_return(@status) - expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm enable -s #{@current_resource.service_name}").and_return(@status) expect(@provider.enable_service).to be_truthy + + # now we are enabled + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) + @provider.load_current_resource + expect(@current_resource.enabled).to be_truthy end end @@ -130,17 +201,20 @@ describe Chef::Provider::Service::Solaris do describe "when disabling the service" do before(:each) do @provider.current_resource = @current_resource - @current_resource.enabled(false) end it "should call svcadm disable -s chef" do - expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm disable -s chef").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@disabled_svc_status) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "disable", "-s", "chef").and_return(@success) + @provider.load_current_resource expect(@provider.disable_service).to be_truthy expect(@current_resource.enabled).to be_falsey end it "should call svcadm disable -s chef for stop_service" do - expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm disable -s chef").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@disabled_svc_status) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "disable", "-s", "chef").and_return(@success) + @provider.load_current_resource expect(@provider.stop_service).to be_truthy expect(@current_resource.enabled).to be_falsey end @@ -149,12 +223,12 @@ describe Chef::Provider::Service::Solaris do describe "when reloading the service" do before(:each) do - @status = double("Process::Status", :exitstatus => 0) @provider.current_resource = @current_resource + allow(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@enabled_svc_status) end it "should call svcadm refresh chef" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/svcadm refresh chef").and_return(@status) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "refresh", "chef") @provider.reload_service end @@ -162,19 +236,16 @@ describe Chef::Provider::Service::Solaris do describe "when the service doesn't exist" do before(:each) do - @stdout_string = "" - @status = double("Status", :exitstatus => 1, :stdout => @stdout) @provider.current_resource = @current_resource + expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", {:returns=>[0, 1]}).and_return(@no_svc_status) end it "should be marked not running" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs -l chef", {:returns=>[0, 1]}).and_return(@status) @provider.service_status expect(@current_resource.running).to be_falsey end it "should be marked not enabled" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs -l chef", {:returns=>[0, 1]}).and_return(@status) @provider.service_status expect(@current_resource.enabled).to be_falsey end |