diff options
Diffstat (limited to 'spec/unit/provider/service')
17 files changed, 1533 insertions, 962 deletions
diff --git a/spec/unit/provider/service/aix_service_spec.rb b/spec/unit/provider/service/aix_service_spec.rb index 802ccee2c7..176d537abb 100644 --- a/spec/unit/provider/service/aix_service_spec.rb +++ b/spec/unit/provider/service/aix_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: Kaustubh <kaustubh@clogeny.com> -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +33,7 @@ describe Chef::Provider::Service::Aix do describe "load current resource" do it "should create a current resource with the name of the new resource and determine the status" do - @status = double("Status", :exitstatus => 0, :stdout => @stdout) + @status = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out!).and_return(@status) expect(Chef::Resource::Service).to receive(:new).and_return(@current_resource) @@ -47,7 +47,7 @@ describe Chef::Provider::Service::Aix do describe "determine current status" do context "when the service is active" do before do - @status = double("Status", :exitstatus => 0, :stdout => "chef chef 12345 active\n") + @status = double("Status", exitstatus: 0, stdout: "chef chef 12345 active\n") end it "current resource is running" do @@ -61,7 +61,7 @@ describe Chef::Provider::Service::Aix do context "when the service is inoperative" do before do - @status = double("Status", :exitstatus => 0, :stdout => "chef chef inoperative\n") + @status = double("Status", exitstatus: 0, stdout: "chef chef inoperative\n") end it "current resource is not running" do @@ -75,7 +75,7 @@ describe Chef::Provider::Service::Aix do context "when there is no such service" do before do - @status = double("Status", :exitstatus => 1, :stdout => "0513-085 The chef Subsystem is not on file.\n") + @status = double("Status", exitstatus: 1, stdout: "0513-085 The chef Subsystem is not on file.\n") end it "current resource is not running" do expect(@provider).to receive(:shell_out!).with("lssrc -s chef").and_return(@status) @@ -90,7 +90,7 @@ describe Chef::Provider::Service::Aix do describe "is resource group" do context "when there are multiple subsystems associated with group" do before do - @status = double("Status", :exitstatus => 0, :stdout => "chef1 chef 12345 active\nchef2 chef 12334 active\nchef3 chef inoperative") + @status = double("Status", exitstatus: 0, stdout: "chef1 chef 12345 active\nchef2 chef 12334 active\nchef3 chef inoperative") end it "service is a group" do @@ -102,7 +102,7 @@ describe Chef::Provider::Service::Aix do context "when there is a single subsystem in the group" do before do - @status = double("Status", :exitstatus => 0, :stdout => "chef1 chef inoperative\n") + @status = double("Status", exitstatus: 0, stdout: "chef1 chef inoperative\n") end it "service is a group" do @@ -114,8 +114,8 @@ describe Chef::Provider::Service::Aix do context "when the service is a subsystem" do before do - @group_status = double("Status", :exitstatus => 1, :stdout => "0513-086 The chef Group is not on file.\n") - @service_status = double("Status", :exitstatus => 0, :stdout => "chef chef inoperative\n") + @group_status = double("Status", exitstatus: 1, stdout: "0513-086 The chef Group is not on file.\n") + @service_status = double("Status", exitstatus: 0, stdout: "chef chef inoperative\n") end it "service is a subsystem" do diff --git a/spec/unit/provider/service/aixinit_service_spec.rb b/spec/unit/provider/service/aixinit_service_spec.rb index 09c177903b..d47bebd0d3 100644 --- a/spec/unit/provider/service/aixinit_service_spec.rb +++ b/spec/unit/provider/service/aixinit_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: kaustubh (<kaustubh@clogeny.com>) -# Copyright:: Copyright 2014-2016, Chef Software, Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ require "spec_helper" describe Chef::Provider::Service::AixInit do before(:each) do @node = Chef::Node.new - @node.automatic_attrs[:command] = { :ps => "fuuuu" } + @node.automatic_attrs[:command] = { ps: "fuuuu" } @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @@ -35,7 +35,7 @@ describe Chef::Provider::Service::AixInit do end describe "load_current_resource" do - it "sets current resource attributes" do + it "sets current resource properties" do expect(@provider).to receive(:set_current_resource_attributes) @provider.load_current_resource @@ -209,7 +209,7 @@ describe Chef::Provider::Service::AixInit do before do @files = ["/etc/rc.d/rc2.d/S20apache", "/etc/rc.d/rc2.d/K80apache"] # FIXME: this is clearly buggy the duplicated keys do not work - #@priority = {2 => [:start, 20], 2 => [:stop, 80]} + # @priority = {2 => [:start, 20], 2 => [:stop, 80]} @priority = { 2 => [:stop, 80] } allow(Dir).to receive(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]chef"]).and_return(@files) @@ -256,7 +256,7 @@ describe Chef::Provider::Service::AixInit do before do files = ["/etc/rc.d/rc2.d/Sapache", "/etc/rc.d/rc2.d/Kapache"] # FIXME: this is clearly buggy the duplicated keys do not work - #@priority = {2 => [:start, ''], 2 => [:stop, '']} + # @priority = {2 => [:start, ''], 2 => [:stop, '']} @priority = { 2 => [:stop, ""] } allow(Dir).to receive(:glob).with(["/etc/rc.d/rc2.d/[SK][0-9][0-9]#{@new_resource.service_name}", "/etc/rc.d/rc2.d/[SK]#{@new_resource.service_name}"]).and_return(files) diff --git a/spec/unit/provider/service/arch_service_spec.rb b/spec/unit/provider/service/arch_service_spec.rb index 506a1616c5..026db3dc75 100644 --- a/spec/unit/provider/service/arch_service_spec.rb +++ b/spec/unit/provider/service/arch_service_spec.rb @@ -1,7 +1,7 @@ # # Author:: Jan Zimmek (<jan.zimmek@web.de>) # Author:: AJ Christensen (<aj@hjksolutions.com>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,24 +26,25 @@ require "ostruct" describe Chef::Provider::Service::Arch, "load_current_resource" do before(:each) do @node = Chef::Node.new - @node.automatic_attrs[:command] = { :ps => "ps -ef" } + @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 }) + @new_resource.supports({ status: false }) @provider = Chef::Provider::Service::Arch.new(@new_resource, @run_context) - allow(::File).to receive(:exists?).with("/etc/rc.conf").and_return(true) + allow(::File).to receive(:exist?).with("/etc/rc.d/chef").and_return(false) + allow(::File).to receive(:exist?).with("/etc/rc.conf").and_return(true) allow(::File).to receive(: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 - allow(@provider).to receive(:shell_out).and_return(OpenStruct.new(:exitstatus => 0, :stdout => "")) + allow(@provider).to receive(:shell_out).and_return(OpenStruct.new(exitstatus: 0, stdout: "")) @provider.load_current_resource expect(@provider.current_resource.service_name).to eq("chef") end @@ -51,22 +52,22 @@ describe Chef::Provider::Service::Arch, "load_current_resource" do describe "when the service supports status" do before do - @new_resource.supports({ :status => true }) + @new_resource.supports({ status: true }) end it "should run '/etc/rc.d/service_name status'" do - expect(@provider).to receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 0)) + expect(@provider).to 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 status command returns 0" do - allow(@provider).to receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 0)) + allow(@provider).to receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(exitstatus: 0)) @provider.load_current_resource expect(@provider.current_resource.running).to be_truthy end it "should set running to false if the status command returns anything except 0" do - allow(@provider).to receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(:exitstatus => 1)) + allow(@provider).to receive(:shell_out).with("/etc/rc.d/chef status").and_return(OpenStruct.new(exitstatus: 1)) @provider.load_current_resource expect(@provider.current_resource.running).to be_falsey end @@ -85,28 +86,28 @@ describe Chef::Provider::Service::Arch, "load_current_resource" do end it "should run the services status command if one has been specified" do - expect(@provider).to receive(:shell_out).with("/etc/rc.d/chefhasmonkeypants status").and_return(OpenStruct.new(:exitstatus => 0)) + expect(@provider).to 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 } + it "should raise error if the node has a nil ps property and no other means to get status" do + @node.automatic_attrs[:command] = { ps: nil } @provider.define_resource_requirements @provider.action = :start expect { @provider.process_resource_requirements }.to 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 => "" } + it "should raise error if the node has an empty ps property and no other means to get status" do + @node.automatic_attrs[:command] = { ps: "" } @provider.define_resource_requirements @provider.action = :start expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service) end it "should fail if file /etc/rc.conf does not exist" do - allow(::File).to receive(:exists?).with("/etc/rc.conf").and_return(false) + allow(::File).to receive(:exist?).with("/etc/rc.conf").and_return(false) expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Service) end @@ -117,22 +118,22 @@ describe Chef::Provider::Service::Arch, "load_current_resource" do 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 = double("Status", :exitstatus => 0, :stdout => @stdout) + @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 = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out!).and_return(@status) - @node.automatic_attrs[:command] = { :ps => "ps -ef" } + @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 + @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 allow(@status).to receive(:stdout).and_return(@stdout) @provider.load_current_resource expect(@provider.current_resource.running).to be_truthy @@ -181,7 +182,7 @@ RUNNING_PS it "should add chef to DAEMONS array" do allow(::File).to receive(:read).with("/etc/rc.conf").and_return("DAEMONS=(network)") expect(@provider).to receive(:update_daemons).with(%w{network chef}) - @provider.enable_service() + @provider.enable_service end end @@ -202,7 +203,7 @@ RUNNING_PS it "should remove chef from DAEMONS array" do allow(::File).to receive(:read).with("/etc/rc.conf").and_return("DAEMONS=(network chef)") expect(@provider).to receive(:update_daemons).with(["network", "!chef"]) - @provider.disable_service() + @provider.disable_service end end @@ -221,14 +222,14 @@ RUNNING_PS # end it "should call the start command if one is specified" do - allow(@new_resource).to receive(:start_command).and_return("/etc/rc.d/chef startyousillysally") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/chef startyousillysally") - @provider.start_service() + @new_resource.start_command("/etc/rc.d/chef startyousillysally") + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/chef startyousillysally", default_env: false) + @provider.start_service end it "should call '/etc/rc.d/service_name start' if no start command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{@new_resource.service_name} start") - @provider.start_service() + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} start", default_env: false) + @provider.start_service end end @@ -247,14 +248,14 @@ RUNNING_PS # end it "should call the stop command if one is specified" do - allow(@new_resource).to receive(:stop_command).and_return("/etc/rc.d/chef itoldyoutostop") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/chef itoldyoutostop") - @provider.stop_service() + @new_resource.stop_command("/etc/rc.d/chef itoldyoutostop") + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/chef itoldyoutostop", default_env: false) + @provider.stop_service end it "should call '/etc/rc.d/service_name stop' if no stop command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{@new_resource.service_name} stop") - @provider.stop_service() + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} stop", default_env: false) + @provider.stop_service end end @@ -274,22 +275,22 @@ RUNNING_PS # end it "should call 'restart' on the service_name if the resource supports it" do - allow(@new_resource).to receive(:supports).and_return({ :restart => true }) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{@new_resource.service_name} restart") - @provider.restart_service() + @new_resource.supports({ restart: true }) + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} restart", default_env: false) + @provider.restart_service end it "should call the restart_command if one has been specified" do - allow(@new_resource).to receive(:restart_command).and_return("/etc/rc.d/chef restartinafire") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{@new_resource.service_name} restartinafire") - @provider.restart_service() + @new_resource.restart_command("/etc/rc.d/chef restartinafire") + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} restartinafire", default_env: false) + @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 expect(@provider).to receive(:stop_service) expect(@provider).to receive(:sleep).with(1) expect(@provider).to receive(:start_service) - @provider.restart_service() + @provider.restart_service end end @@ -309,15 +310,15 @@ RUNNING_PS # end it "should call 'reload' on the service if it supports it" do - allow(@new_resource).to receive(:supports).and_return({ :reload => true }) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{@new_resource.service_name} reload") - @provider.reload_service() + @new_resource.supports({ reload: true }) + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} reload", default_env: false) + @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 - allow(@new_resource).to receive(:reload_command).and_return("/etc/rc.d/chef lollerpants") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{@new_resource.service_name} lollerpants") - @provider.reload_service() + @new_resource.reload_command("/etc/rc.d/chef lollerpants") + expect(@provider).to receive(:shell_out!).with("/etc/rc.d/#{@new_resource.service_name} lollerpants", default_env: false) + @provider.reload_service end end end diff --git a/spec/unit/provider/service/debian_service_spec.rb b/spec/unit/provider/service/debian_service_spec.rb index 799ed991a3..d0cd048c4f 100644 --- a/spec/unit/provider/service/debian_service_spec.rb +++ b/spec/unit/provider/service/debian_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen (<aj@hjksolutions.com>) -# Copyright:: Copyright 2008-2016, HJK Solutions, LLC +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ require "spec_helper" describe Chef::Provider::Service::Debian do before(:each) do @node = Chef::Node.new - @node.automatic_attrs[:command] = { :ps => "fuuuu" } + @node.automatic_attrs[:command] = { ps: "fuuuu" } @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @@ -32,11 +32,22 @@ describe Chef::Provider::Service::Debian do @provider.current_resource = @current_resource @pid, @stdin, @stdout, @stderr = nil, nil, nil, nil + allow(File).to receive(:exist?).with("/etc/init.d/chef").and_return true + end + + let(:init_lines) do + [ + "### BEGIN INIT INFO", + "# Required-Start: hostname $local_fs", + "# Default-Start: 2 3 4 5", + "# Default-Stop: 0 1 6", + "### END INIT INFO", + ] end describe "load_current_resource" do it "ensures /usr/sbin/update-rc.d is available" do - expect(File).to receive(:exists?).with("/usr/sbin/update-rc.d") .and_return(false) + expect(File).to receive(:exist?).with("/usr/sbin/update-rc.d").and_return(false) @provider.define_resource_requirements expect do @@ -47,23 +58,14 @@ describe Chef::Provider::Service::Debian do context "when update-rc.d shows init linked to rc*.d/" do before do allow(@provider).to receive(:assert_update_rcd_available) + allow(File).to receive(:readlines).with("/etc/init.d/chef").and_return(init_lines) - 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 = double("Status", :exitstatus => 0, :stdout => @stdout) - allow(@provider).to receive(:shell_out!).and_return(@status) - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + [0, 1, 6].each do |stop| + allow(Dir).to receive(:glob).with("/etc/rc#{stop}.d/[SK][0-9][0-9]chef").and_return(["/etc/rc#{stop}.d/K20chef"]) + end + [2, 3, 4, 5].each do |start| + allow(Dir).to receive(:glob).with("/etc/rc#{start}.d/[SK][0-9][0-9]chef").and_return(["/etc/rc#{start}.d/S20chef"]) + end end it "says the service is enabled" do @@ -75,18 +77,35 @@ describe Chef::Provider::Service::Debian do expect(@provider.load_current_resource).to equal(@current_resource) expect(@current_resource.enabled).to be_truthy end + + it "stores the start/stop priorities of the service" do + @provider.load_current_resource + expect(@provider.current_resource.priority).to eq( + { + "2" => [:start, "20"], + "3" => [:start, "20"], + "4" => [:start, "20"], + "5" => [:start, "20"], + "0" => [:stop, "20"], + "1" => [:stop, "20"], + "6" => [:stop, "20"], + } + ) + end end context "when update-rc.d shows init isn't linked to rc*.d/" do before do allow(@provider).to receive(:assert_update_rcd_available) - @status = double("Status", :exitstatus => 0) - @stdout = StringIO.new( - " Removing any system startup links for /etc/init.d/chef ...") - @stderr = StringIO.new - @status = double("Status", :exitstatus => 0, :stdout => @stdout) - allow(@provider).to receive(:shell_out!).and_return(@status) - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + + allow(File).to receive(:readlines).with("/etc/init.d/chef").and_return(init_lines) + + [0, 1, 6].each do |stop| + allow(Dir).to receive(:glob).with("/etc/rc#{stop}.d/[SK][0-9][0-9]chef").and_return([]) + end + [2, 3, 4, 5].each do |start| + allow(Dir).to receive(:glob).with("/etc/rc#{start}.d/[SK][0-9][0-9]chef").and_return([]) + end end it "says the service is disabled" do @@ -100,150 +119,6 @@ describe Chef::Provider::Service::Debian do end end - context "when update-rc.d fails" do - before do - @status = double("Status", :exitstatus => -1) - allow(@provider).to receive(:popen4).and_return(@status) - end - - it "raises an error" do - @provider.define_resource_requirements - expect do - @provider.process_resource_requirements - end.to raise_error(Chef::Exceptions::Service) - end - end - - { "Debian/Lenny and older" => { - "linked" => { - "stdout" => <<-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 - STDOUT - "stderr" => "", - "priorities" => { - "0" => [:stop, "20"], - "1" => [:stop, "20"], - "2" => [:start, "20"], - "3" => [:start, "20"], - "4" => [:start, "20"], - "5" => [:start, "20"], - "6" => [:stop, "20"], - }, - }, - "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" => <<-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 - STDERR - "priorities" => { - "0" => [:stop, "20"], - "1" => [:stop, "20"], - "2" => [:start, "20"], - "3" => [:start, "20"], - "4" => [:start, "20"], - "5" => [:start, "20"], - "6" => [:stop, "20"], - }, - }, - "not linked" => { - "stdout" => "update-rc.d: using dependency based boot sequencing", - "stderr" => "", - }, - }, - "Debian/Wheezy and earlier, a service only starting at run level S" => { - "linked" => { - "stdout" => "", - "stderr" => <<-STDERR, -insserv: remove service /etc/init.d/../rc0.d/K06rpcbind -insserv: remove service /etc/init.d/../rc1.d/K06rpcbind -insserv: remove service /etc/init.d/../rc6.d/K06rpcbind -insserv: remove service /etc/init.d/../rcS.d/S13rpcbind -insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop - STDERR - "priorities" => { - "0" => [:stop, "06"], - "1" => [:stop, "06"], - "6" => [:stop, "06"], - "S" => [:start, "13"], - }, - }, - "not linked" => { - "stdout" => "", - "stderr" => "insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop", - }, - }, - }.each do |model, expected_results| - context "on #{model}" do - context "when update-rc.d shows init linked to rc*.d/" do - before do - allow(@provider).to receive(:assert_update_rcd_available) - - @stdout = StringIO.new(expected_results["linked"]["stdout"]) - @stderr = StringIO.new(expected_results["linked"]["stderr"]) - @status = double("Status", :exitstatus => 0, :stdout => @stdout) - allow(@provider).to receive(:shell_out!).and_return(@status) - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) - end - - it "says the service is enabled" do - expect(@provider.service_currently_enabled?(@provider.get_priority)).to be_truthy - end - - it "stores the 'enabled' state" do - allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource) - expect(@provider.load_current_resource).to equal(@current_resource) - expect(@current_resource.enabled).to be_truthy - end - - it "stores the start/stop priorities of the service" do - @provider.load_current_resource - expect(@provider.current_resource.priority).to eq(expected_results["linked"]["priorities"]) - end - end - - context "when update-rc.d shows init isn't linked to rc*.d/" do - before do - allow(@provider).to receive(:assert_update_rcd_available) - @stdout = StringIO.new(expected_results["not linked"]["stdout"]) - @stderr = StringIO.new(expected_results["not linked"]["stderr"]) - @status = double("Status", :exitstatus => 0, :stdout => @stdout) - allow(@provider).to receive(:shell_out!).and_return(@status) - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) - end - - it "says the service is disabled" do - expect(@provider.service_currently_enabled?(@provider.get_priority)).to be_falsey - end - - it "stores the 'disabled' state" do - allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource) - expect(@provider.load_current_resource).to equal(@current_resource) - expect(@current_resource.enabled).to be_falsey - end - end - end - end - end describe "action_enable" do @@ -308,21 +183,21 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop describe "enable_service" do let(:service_name) { @new_resource.service_name } context "when the service doesn't set a priority" do - it "calls update-rc.d 'service_name' defaults" do + it "assumes default priority 20 and calls update-rc.d remove => defaults 20 80" do expect_commands(@provider, [ "/usr/sbin/update-rc.d -f #{service_name} remove", - "/usr/sbin/update-rc.d #{service_name} defaults", + "/usr/sbin/update-rc.d #{service_name} defaults 20 80", ]) @provider.enable_service end end - context "when the service sets a simple priority" do + context "when the service sets a simple priority 75" do before do @new_resource.priority(75) end - it "calls update-rc.d 'service_name' defaults" do + it "calls update-rc.d remove => defaults 75 25" do expect_commands(@provider, [ "/usr/sbin/update-rc.d -f #{service_name} remove", "/usr/sbin/update-rc.d #{service_name} defaults 75 25", @@ -331,15 +206,17 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop end end - context "when the service sets complex priorities" do + context "when the service sets complex priorities using Hash" do before do @new_resource.priority(2 => [:start, 20], 3 => [:stop, 55]) end - it "calls update-rc.d 'service_name' with those priorities" do + it "calls update-rc.d remove => defaults => enable|disable <runlevel>" do expect_commands(@provider, [ "/usr/sbin/update-rc.d -f #{service_name} remove", - "/usr/sbin/update-rc.d #{service_name} start 20 2 . stop 55 3 . ", + "/usr/sbin/update-rc.d #{service_name} defaults", + "/usr/sbin/update-rc.d #{service_name} enable 2", + "/usr/sbin/update-rc.d #{service_name} disable 3", ]) @provider.enable_service end @@ -348,25 +225,44 @@ insserv: dryrun, not creating .depend.boot, .depend.start, and .depend.stop describe "disable_service" do let(:service_name) { @new_resource.service_name } + context "when the service doesn't set a priority" do - it "calls update-rc.d -f 'service_name' remove + stop with default priority" do + it "calls update-rc.d remove => defaults => disable" do expect_commands(@provider, [ "/usr/sbin/update-rc.d -f #{service_name} remove", - "/usr/sbin/update-rc.d -f #{service_name} stop 80 2 3 4 5 .", + "/usr/sbin/update-rc.d #{service_name} defaults", + "/usr/sbin/update-rc.d #{service_name} disable", ]) @provider.disable_service end end - context "when the service sets a simple priority" do + context "when the service sets a simple priority 75" do before do @new_resource.priority(75) end - it "calls update-rc.d -f 'service_name' remove + stop with the specified priority" do + it "ignores priority and calls update-rc.d remove => defaults => disable" do expect_commands(@provider, [ "/usr/sbin/update-rc.d -f #{service_name} remove", - "/usr/sbin/update-rc.d -f #{service_name} stop #{100 - @new_resource.priority} 2 3 4 5 .", + "/usr/sbin/update-rc.d #{service_name} defaults", + "/usr/sbin/update-rc.d #{service_name} disable", + ]) + @provider.disable_service + end + end + + context "when the service sets complex priorities using Hash" do + before do + @new_resource.priority(2 => [:start, 20], 3 => [:stop, 55]) + end + + it "ignores priority and calls update-rc.d remove => defaults => enable|disable <runlevel>" do + expect_commands(@provider, [ + "/usr/sbin/update-rc.d -f #{service_name} remove", + "/usr/sbin/update-rc.d #{service_name} defaults", + "/usr/sbin/update-rc.d #{service_name} enable 2", + "/usr/sbin/update-rc.d #{service_name} disable 3", ]) @provider.disable_service end diff --git a/spec/unit/provider/service/freebsd_service_spec.rb b/spec/unit/provider/service/freebsd_service_spec.rb index 10eb3c1a14..4392786edc 100644 --- a/spec/unit/provider/service/freebsd_service_spec.rb +++ b/spec/unit/provider/service/freebsd_service_spec.rb @@ -27,14 +27,14 @@ end describe Chef::Provider::Service::Freebsd do let(:node) do node = Chef::Node.new - node.automatic_attrs[:command] = { :ps => "ps -ax" } + node.automatic_attrs[:command] = { ps: "ps -ax" } node end let(:new_resource) do new_resource = Chef::Resource::Service.new("apache22") new_resource.pattern("httpd") - new_resource.supports({ :status => false }) + new_resource.supports({ status: false }) new_resource end @@ -99,7 +99,7 @@ describe Chef::Provider::Service::Freebsd do end context "when a status command has been specified" do - let(:status) { double(:stdout => "", :exitstatus => 0) } + let(:status) { double(stdout: "", exitstatus: 0) } before do new_resource.status_command("/bin/chefhasmonkeypants status") @@ -112,10 +112,10 @@ describe Chef::Provider::Service::Freebsd do end context "when the service supports status" do - let(:status) { double(:stdout => "", :exitstatus => 0) } + let(:status) { double(stdout: "", exitstatus: 0) } before do - new_resource.supports({ :status => true }) + new_resource.supports({ status: true }) end it "should run '/etc/init.d/service_name status'" do @@ -136,18 +136,18 @@ describe Chef::Provider::Service::Freebsd do end end - context "when we have a 'ps' attribute" do + context "when we have a 'ps' property" do let(:stdout) do - 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 + 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 end - let(:status) { double(:stdout => stdout, :exitstatus => 0) } + let(:status) { double(stdout: stdout, exitstatus: 0) } before do - node.automatic_attrs[:command] = { :ps => "ps -ax" } + node.automatic_attrs[:command] = { ps: "ps -ax" } end it "should shell_out! the node's ps command" do @@ -163,9 +163,9 @@ PS_SAMPLE context "when the regex matches the output" do let(:stdout) do - StringIO.new(<<-PS_SAMPLE) -555 ?? Ss 0:05.16 /usr/sbin/cron -s - 9881 ?? Ss 0:06.67 /usr/local/sbin/httpd -DNOHTTPACCEPT + StringIO.new(<<~PS_SAMPLE) + 555 ?? Ss 0:05.16 /usr/sbin/cron -s + 9881 ?? Ss 0:06.67 /usr/local/sbin/httpd -DNOHTTPACCEPT PS_SAMPLE end @@ -191,7 +191,7 @@ PS_SAMPLE context "when ps is empty string" do before do - node.automatic_attrs[:command] = { :ps => "" } + node.automatic_attrs[:command] = { ps: "" } end it "should set running to nil" do @@ -261,7 +261,8 @@ PS_SAMPLE [ %Q{thing_#{new_resource.service_name}_enable="YES"}, %Q{#{new_resource.service_name}_enable="NO"}, - ] end + ] + end it "sets enabled based on the exact match (false)" do provider.determine_enabled_status! expect(current_resource.enabled).to be false @@ -273,7 +274,8 @@ PS_SAMPLE [ %Q{#{new_resource.service_name}_thing_enable="YES"}, %Q{#{new_resource.service_name}_enable="NO"}, - ] end + ] + end it "sets enabled based on the exact match (false)" do provider.determine_enabled_status! expect(current_resource.enabled).to be false @@ -285,7 +287,8 @@ PS_SAMPLE [ %Q{thing_#{new_resource.service_name}_enable="NO"}, %Q{#{new_resource.service_name}_enable="YES"}, - ] end + ] + end it "sets enabled based on the exact match (true)" do provider.determine_enabled_status! expect(current_resource.enabled).to be true @@ -297,7 +300,8 @@ PS_SAMPLE [ %Q{#{new_resource.service_name}_thing_enable="NO"}, %Q{#{new_resource.service_name}_enable="YES"}, - ] end + ] + end it "sets enabled based on the exact match (true)" do provider.determine_enabled_status! expect(current_resource.enabled).to be true @@ -341,10 +345,10 @@ PS_SAMPLE context "when the rc script has a 'name' variable" do let(:rcscript) do - StringIO.new(<<-EOF) -name="#{new_resource.service_name}" -rcvar=`set_rcvar` -EOF + StringIO.new(<<~EOF) + name="#{new_resource.service_name}" + rcvar=`set_rcvar` + EOF end it "should not raise an exception if the rcscript have a name variable" do @@ -363,24 +367,24 @@ EOF describe "when the rcscript does not have a name variable" do let(:rcscript) do - StringIO.new <<-EOF -rcvar=`set_rcvar` -EOF + StringIO.new <<~EOF + rcvar=`set_rcvar` + EOF end before do - status = double(:stdout => rcvar_stdout, :exitstatus => 0) + status = double(stdout: rcvar_stdout, exitstatus: 0) allow(provider).to receive(:shell_out!).with("/usr/local/etc/rc.d/#{new_resource.service_name} rcvar").and_return(status) end describe "when rcvar returns foobar_enable" do let(:rcvar_stdout) do - rcvar_stdout = <<-EOF -# apache22 -# -# #{new_resource.service_name}_enable="YES" -# (default: "") -EOF + rcvar_stdout = <<~EOF + # apache22 + # + # #{new_resource.service_name}_enable="YES" + # (default: "") + EOF end it "should get the service name from rcvar if the rcscript does not have a name variable" do @@ -394,10 +398,10 @@ EOF describe "when rcvar does not return foobar_enable" do let(:rcvar_stdout) do - rcvar_stdout = <<-EOF -# service_with_noname -# -EOF + rcvar_stdout = <<~EOF + # service_with_noname + # + EOF end it "should return nil" do @@ -444,46 +448,46 @@ EOF describe Chef::Provider::Service::Freebsd, "start_service" do it "should call the start command if one is specified" do new_resource.start_command("/etc/rc.d/chef startyousillysally") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/chef startyousillysally") - provider.start_service() + expect(provider).to receive(:shell_out!).with("/etc/rc.d/chef startyousillysally", default_env: false) + provider.start_service end it "should call '/usr/local/etc/rc.d/service_name faststart' if no start command is specified" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("/usr/local/etc/rc.d/#{new_resource.service_name} faststart") - provider.start_service() + expect(provider).to receive(:shell_out!).with("/usr/local/etc/rc.d/#{new_resource.service_name} faststart", default_env: false) + provider.start_service end end describe Chef::Provider::Service::Freebsd, "stop_service" do it "should call the stop command if one is specified" do new_resource.stop_command("/etc/init.d/chef itoldyoutostop") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef itoldyoutostop") - provider.stop_service() + expect(provider).to receive(:shell_out!).with("/etc/init.d/chef itoldyoutostop", default_env: false) + provider.stop_service end it "should call '/usr/local/etc/rc.d/service_name faststop' if no stop command is specified" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("/usr/local/etc/rc.d/#{new_resource.service_name} faststop") - provider.stop_service() + expect(provider).to receive(:shell_out!).with("/usr/local/etc/rc.d/#{new_resource.service_name} faststop", default_env: false) + provider.stop_service end end describe Chef::Provider::Service::Freebsd, "restart_service" do it "should call 'restart' on the service_name if the resource supports it" do - new_resource.supports({ :restart => true }) - expect(provider).to receive(:shell_out_with_systems_locale!).with("/usr/local/etc/rc.d/#{new_resource.service_name} fastrestart") - provider.restart_service() + new_resource.supports({ restart: true }) + expect(provider).to receive(:shell_out!).with("/usr/local/etc/rc.d/#{new_resource.service_name} fastrestart", default_env: false) + 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") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef restartinafire") - provider.restart_service() + expect(provider).to receive(:shell_out!).with("/etc/init.d/chef restartinafire", default_env: false) + provider.restart_service end it "otherwise it should call stop and start" do expect(provider).to receive(:stop_service) expect(provider).to receive(:start_service) - provider.restart_service() + provider.restart_service end end end @@ -550,21 +554,21 @@ EOF allow(current_resource).to receive(:enabled).and_return(false) expect(provider).to receive(:read_rc_conf).and_return([ "foo", "#{new_resource.service_name}_enable=\"NO\"", "bar" ]) expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"YES\""]) - provider.enable_service() + provider.enable_service end it "should not partial match an already enabled service" do allow(current_resource).to receive(:enabled).and_return(false) expect(provider).to receive(:read_rc_conf).and_return([ "foo", "thing_#{new_resource.service_name}_enable=\"NO\"", "bar" ]) expect(provider).to receive(:write_rc_conf).with(["foo", "thing_#{new_resource.service_name}_enable=\"NO\"", "bar", "#{new_resource.service_name}_enable=\"YES\""]) - provider.enable_service() + provider.enable_service end it "should enable the service if it is not enabled and not already specified in the rc.conf file" do allow(current_resource).to receive(:enabled).and_return(false) expect(provider).to receive(:read_rc_conf).and_return(%w{foo bar}) expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"YES\""]) - provider.enable_service() + provider.enable_service end it "should not enable the service if it is already enabled" do @@ -577,7 +581,7 @@ EOF allow(current_resource).to receive(:enabled).and_return(false) expect(provider).to receive(:read_rc_conf).and_return([ "foo", "bar", "\# #{new_resource.service_name}_enable=\"YES\"", "\# #{new_resource.service_name}_enable=\"NO\""]) expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"YES\""]) - provider.enable_service() + provider.enable_service end end @@ -591,27 +595,27 @@ EOF allow(current_resource).to receive(:enabled).and_return(true) expect(provider).to receive(:read_rc_conf).and_return([ "foo", "#{new_resource.service_name}_enable=\"YES\"", "bar" ]) expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"NO\""]) - provider.disable_service() + provider.disable_service end it "should not disable an enabled service that partially matches" do allow(current_resource).to receive(:enabled).and_return(true) expect(provider).to receive(:read_rc_conf).and_return([ "foo", "thing_#{new_resource.service_name}_enable=\"YES\"", "bar" ]) expect(provider).to receive(:write_rc_conf).with(["foo", "thing_#{new_resource.service_name}_enable=\"YES\"", "bar", "#{new_resource.service_name}_enable=\"NO\""]) - provider.disable_service() + provider.disable_service end it "should not disable the service if it is already disabled" do allow(current_resource).to receive(:enabled).and_return(false) expect(provider).not_to receive(:write_rc_conf) - provider.disable_service() + provider.disable_service end it "should remove commented out versions of it being disabled or enabled" do allow(current_resource).to receive(:enabled).and_return(true) expect(provider).to receive(:read_rc_conf).and_return([ "foo", "bar", "\# #{new_resource.service_name}_enable=\"YES\"", "\# #{new_resource.service_name}_enable=\"NO\""]) expect(provider).to receive(:write_rc_conf).with(["foo", "bar", "#{new_resource.service_name}_enable=\"NO\""]) - provider.disable_service() + 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 index a00ca7aadd..f195fbe40b 100644 --- a/spec/unit/provider/service/gentoo_service_spec.rb +++ b/spec/unit/provider/service/gentoo_service_spec.rb @@ -1,7 +1,7 @@ # # Author:: Lee Jensen (<ljensen@engineyard.com>) # Author:: AJ Christensen (<aj@chef.io>) -# Copyright:: Copyright 2008-2016, Chef Software, Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,18 +30,18 @@ describe Chef::Provider::Service::Gentoo do @provider = Chef::Provider::Service::Gentoo.new(@new_resource, @run_context) allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource) - @status = double("Status", :exitstatus => 0, :stdout => @stdout) + @status = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out).and_return(@status) - allow(File).to receive(:exists?).with("/etc/init.d/chef").and_return(true) - allow(File).to receive(:exists?).with("/sbin/rc-update").and_return(true) - allow(File).to receive(:exists?).with("/etc/runlevels/default/chef").and_return(false) + allow(File).to receive(:exist?).with("/etc/init.d/chef").and_return(true) + allow(File).to receive(:exist?).with("/sbin/rc-update").and_return(true) + allow(File).to receive(:exist?).with("/etc/runlevels/default/chef").and_return(false) allow(File).to receive(:readable?).with("/etc/runlevels/default/chef").and_return(false) end - # new test: found_enabled state + # new test: found_enabled state # describe "load_current_resource" do it "should raise Chef::Exceptions::Service if /sbin/rc-update does not exist" do - expect(File).to receive(:exists?).with("/sbin/rc-update").and_return(false) + expect(File).to receive(:exist?).with("/sbin/rc-update").and_return(false) @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service) end @@ -65,7 +65,7 @@ describe Chef::Provider::Service::Gentoo do describe "and the file exists and is readable" do before do - allow(File).to receive(:exists?).with("/etc/runlevels/default/chef").and_return(true) + allow(File).to receive(:exist?).with("/etc/runlevels/default/chef").and_return(true) allow(File).to receive(:readable?).with("/etc/runlevels/default/chef").and_return(true) end it "should set enabled to true" do @@ -76,7 +76,7 @@ describe Chef::Provider::Service::Gentoo do describe "and the file exists but is not readable" do before do - allow(File).to receive(:exists?).with("/etc/runlevels/default/chef").and_return(true) + allow(File).to receive(:exist?).with("/etc/runlevels/default/chef").and_return(true) allow(File).to receive(:readable?).with("/etc/runlevels/default/chef").and_return(false) end @@ -88,7 +88,7 @@ describe Chef::Provider::Service::Gentoo do describe "and the file does not exist" do before do - allow(File).to receive(:exists?).with("/etc/runlevels/default/chef").and_return(false) + allow(File).to receive(:exist?).with("/etc/runlevels/default/chef").and_return(false) allow(File).to receive(:readable?).with("/etc/runlevels/default/chef").and_return("foobarbaz") end @@ -129,14 +129,14 @@ describe Chef::Provider::Service::Gentoo do describe Chef::Provider::Service::Gentoo, "enable_service" do it "should call rc-update add *service* default" do expect(@provider).to receive(:shell_out!).with("/sbin/rc-update add chef default") - @provider.enable_service() + @provider.enable_service end end describe Chef::Provider::Service::Gentoo, "disable_service" do it "should call rc-update del *service* default" do expect(@provider).to receive(:shell_out!).with("/sbin/rc-update del chef default") - @provider.disable_service() + @provider.disable_service end end end diff --git a/spec/unit/provider/service/init_service_spec.rb b/spec/unit/provider/service/init_service_spec.rb index 4b31e9c399..6f60cc717d 100644 --- a/spec/unit/provider/service/init_service_spec.rb +++ b/spec/unit/provider/service/init_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen (<aj@hjksolutions.com>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ 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" } + @node.automatic_attrs[:command] = { ps: "ps -ef" } @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @@ -32,12 +32,12 @@ describe Chef::Provider::Service::Init, "load_current_resource" do @provider = Chef::Provider::Service::Init.new(@new_resource, @run_context) allow(Chef::Resource::Service).to receive(: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 = double("Status", :exitstatus => 0, :stdout => @stdout) + @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 = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out!).and_return(@status) end @@ -53,7 +53,7 @@ PS describe "when the service supports status" do before do - @new_resource.supports({ :status => true }) + @new_resource.supports({ status: true }) end it "should run '/etc/init.d/service_name status'" do @@ -83,7 +83,7 @@ PS describe "when a status command has been specified" do before do - allow(@new_resource).to receive(:status_command).and_return("/etc/init.d/chefhasmonkeypants status") + @new_resource.status_command("/etc/init.d/chefhasmonkeypants status") end it "should run the services status command if one has been specified" do @@ -95,12 +95,12 @@ PS describe "when an init command has been specified" do before do - allow(@new_resource).to receive(:init_command).and_return("/opt/chef-server/service/erchef") + @new_resource.init_command("/opt/chef-server/service/erchef") @provider = Chef::Provider::Service::Init.new(@new_resource, @run_context) end it "should use the init_command if one has been specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/opt/chef-server/service/erchef start") + expect(@provider).to receive(:shell_out!).with("/opt/chef-server/service/erchef start", default_env: false) @provider.start_service end @@ -108,16 +108,16 @@ PS 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 } + it "should raise an error if the node has a nil ps property" do + @node.automatic_attrs[:command] = { ps: nil } @provider.load_current_resource @provider.action = :start @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to 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 => "" } + it "should raise an error if the node has an empty ps property" do + @node.automatic_attrs[:command] = { ps: "" } @provider.load_current_resource @provider.action = :start @provider.define_resource_requirements @@ -126,17 +126,17 @@ PS end - describe "when we have a 'ps' attribute" do + describe "when we have a 'ps' property" do it "should shell_out! the node's ps command" do expect(@provider).to 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 + @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 allow(@status).to receive(:stdout).and_return(@stdout) @provider.load_current_resource expect(@current_resource.running).to be_truthy @@ -164,68 +164,68 @@ RUNNING_PS 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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef startyousillysally") - @provider.start_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/chef startyousillysally", default_env: false) + @provider.start_service end it "should call '/etc/init.d/service_name start' if no start command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/#{@new_resource.service_name} start") - @provider.start_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} start", default_env: false) + @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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef itoldyoutostop") - @provider.stop_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/chef itoldyoutostop", default_env: false) + @provider.stop_service end it "should call '/etc/init.d/service_name stop' if no stop command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/#{@new_resource.service_name} stop") - @provider.stop_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} stop", default_env: false) + @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 }) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/#{@new_resource.service_name} restart") - @provider.restart_service() + @new_resource.supports({ restart: true }) + expect(@provider).to receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} restart", default_env: false) + @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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/#{@new_resource.service_name} restartinafire") - @provider.restart_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/#{@new_resource.service_name} restartinafire", default_env: false) + @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 expect(@provider).to receive(:stop_service) expect(@provider).to receive(:sleep).with(1) expect(@provider).to receive(:start_service) - @provider.restart_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 }) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef reload") - @provider.reload_service() + @new_resource.supports({ reload: true }) + expect(@provider).to receive(:shell_out!).with("/etc/init.d/chef reload", default_env: false) + @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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef lollerpants") - @provider.reload_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/chef lollerpants", default_env: false) + @provider.reload_service end end describe "when a custom command has been specified" do before do @new_resource.start_command("/etc/init.d/chef startyousillysally") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef startyousillysally") + expect(@provider).to receive(:shell_out!).with("/etc/init.d/chef startyousillysally", default_env: false) end it "should still pass all why run assertions" do diff --git a/spec/unit/provider/service/insserv_service_spec.rb b/spec/unit/provider/service/insserv_service_spec.rb index 3b2b19c432..a46e8745fc 100644 --- a/spec/unit/provider/service/insserv_service_spec.rb +++ b/spec/unit/provider/service/insserv_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: Bryan McLellan <btm@loftninjas.org> -# Copyright:: Copyright 2011-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,20 +23,20 @@ describe Chef::Provider::Service::Insserv do @node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) - @node.automatic_attrs[:command] = { :ps => "ps -ax" } + @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 = double("Process::Status mock", :exitstatus => 0, :stdout => "") + @status = double("Process::Status mock", exitstatus: 0, stdout: "") allow(@provider).to receive(:shell_out!).and_return(@status) end describe "load_current_resource" do describe "when startup links exist" do before do - allow(Dir).to receive(:glob).with("/etc/rc**/S*initgrediant").and_return(["/etc/rc5.d/S18initgrediant", "/etc/rc2.d/S18initgrediant", "/etc/rc4.d/S18initgrediant", "/etc/rc3.d/S18initgrediant"]) + allow(Dir).to receive(:glob).with("/etc/rc*/**/S*initgrediant").and_return(["/etc/rc.d/rc5.d/S18initgrediant", "/etc/rc.d/rc2.d/S18initgrediant", "/etc/rc.d/rc4.d/S18initgrediant", "/etc/rc.d/rc3.d/S18initgrediant"]) end it "sets the current enabled status to true" do @@ -47,7 +47,7 @@ describe Chef::Provider::Service::Insserv do describe "when startup links do not exist" do before do - allow(Dir).to receive(:glob).with("/etc/rc**/S*initgrediant").and_return([]) + allow(Dir).to receive(:glob).with("/etc/rc*/**/S*initgrediant").and_return([]) end it "sets the current enabled status to false" do diff --git a/spec/unit/provider/service/invokercd_service_spec.rb b/spec/unit/provider/service/invokercd_service_spec.rb index 57b13d0c51..cff02f045b 100644 --- a/spec/unit/provider/service/invokercd_service_spec.rb +++ b/spec/unit/provider/service/invokercd_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: AJ Christensen (<aj@hjksolutions.com>) -# Copyright:: Copyright 2008-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,7 @@ 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" } + @node.automatic_attrs[:command] = { ps: "ps -ef" } @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @@ -32,12 +32,12 @@ describe Chef::Provider::Service::Invokercd, "load_current_resource" do @provider = Chef::Provider::Service::Invokercd.new(@new_resource, @run_context) allow(Chef::Resource::Service).to receive(: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 = double("Status", :exitstatus => 0, :stdout => @stdout) + @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 = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out!).and_return(@status) end @@ -53,7 +53,7 @@ PS describe "when the service supports status" do before do - @new_resource.supports({ :status => true }) + @new_resource.supports({ status: true }) end it "should run '/usr/sbin/invoke-rc.d service_name status'" do @@ -83,7 +83,7 @@ PS describe "when a status command has been specified" do before do - allow(@new_resource).to receive(:status_command).and_return("/usr/sbin/invoke-rc.d chefhasmonkeypants status") + @new_resource.status_command("/usr/sbin/invoke-rc.d chefhasmonkeypants status") end it "should run the services status command if one has been specified" do @@ -94,15 +94,15 @@ PS 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 } + it "should raise error if the node has a nil ps property and no other means to get status" do + @node.automatic_attrs[:command] = { ps: nil } @provider.action = :start @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to 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 => "" } + it "should raise error if the node has an empty ps property and no other means to get status" do + @node.automatic_attrs[:command] = { ps: "" } @provider.action = :start @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service) @@ -110,26 +110,26 @@ PS end - describe "when we have a 'ps' attribute" do + describe "when we have a 'ps' property" do it "should shell_out! the node's ps command" do - @status = double("Status", :exitstatus => 0, :stdout => @stdout) + @status = double("Status", exitstatus: 0, stdout: @stdout) expect(@provider).to 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 = double("Status", :exitstatus => 0, :stdout => @stdout) + @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 = double("Status", exitstatus: 0, stdout: @stdout) expect(@provider).to receive(:shell_out!).and_return(@status) @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to false if the regex doesn't match" do - @status = double("Status", :exitstatus => 0, :stdout => @stdout) + @status = double("Status", exitstatus: 0, stdout: @stdout) expect(@provider).to receive(:shell_out!).and_return(@status) @provider.load_current_resource expect(@current_resource.running).to be_falsey @@ -151,61 +151,61 @@ RUNNING_PS 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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d chef startyousillysally") - @provider.start_service() + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef startyousillysally", default_env: false) + @provider.start_service end it "should call '/usr/sbin/invoke-rc.d service_name start' if no start command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} start") - @provider.start_service() + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} start", default_env: false) + @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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d chef itoldyoutostop") - @provider.stop_service() + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef itoldyoutostop", default_env: false) + @provider.stop_service end it "should call '/usr/sbin/invoke-rc.d service_name stop' if no stop command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} stop") - @provider.stop_service() + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} stop", default_env: false) + @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 }) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} restart") - @provider.restart_service() + @new_resource.supports({ restart: true }) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} restart", default_env: false) + @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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} restartinafire") - @provider.restart_service() + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d #{@new_resource.service_name} restartinafire", default_env: false) + @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 expect(@provider).to receive(:stop_service) expect(@provider).to receive(:sleep).with(1) expect(@provider).to receive(:start_service) - @provider.restart_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 }) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d chef reload") - @provider.reload_service() + @new_resource.supports({ reload: true }) + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef reload", default_env: false) + @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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/usr/sbin/invoke-rc.d chef lollerpants") - @provider.reload_service() + expect(@provider).to receive(:shell_out!).with("/usr/sbin/invoke-rc.d chef lollerpants", default_env: false) + @provider.reload_service end end end diff --git a/spec/unit/provider/service/macosx_spec.rb b/spec/unit/provider/service/macosx_spec.rb index 12f97431ba..6cc0f88725 100644 --- a/spec/unit/provider/service/macosx_spec.rb +++ b/spec/unit/provider/service/macosx_spec.rb @@ -1,6 +1,7 @@ # # Author:: Igor Afonov <afonov@gmail.com> # Copyright:: Copyright 2011-2016, Igor Afonov +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,288 +45,288 @@ describe Chef::Provider::Service::Macosx do context "when service name is given as" do let(:node) { Chef::Node.new } let(:events) { Chef::EventDispatch::Dispatcher.new } + let(:logger) { double("Mixlib::Log::Child").as_null_object } let(:run_context) { Chef::RunContext.new(node, {}, events) } let(:provider) { described_class.new(new_resource, run_context) } let(:launchctl_stdout) { StringIO.new } - let(:plutil_stdout) { String.new <<-XML } -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Label</key> - <string>io.redis.redis-server</string> -</dict> -</plist> -XML + let(:plutil_stdout) { String.new <<~XML } + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>Label</key> + <string>io.redis.redis-server</string> + </dict> + </plist> + XML %w{Daemon Agent}.each do |service_type| ["redis-server", "io.redis.redis-server"].each do |service_name| - ["10.9", "10.10", "10.11"].each do |platform_version| - let(:plist) { "/Library/LaunchDaemons/io.redis.redis-server.plist" } - let(:session) { StringIO.new } - if service_type == "Agent" - let(:plist) { "/Library/LaunchAgents/io.redis.redis-server.plist" } - let(:session) { "-S Aqua " } - let(:su_cmd) { "su -l igor -c" } - if platform_version == "10.9" - let(:su_cmd) { "su igor -c" } - end - end - let(:service_label) { "io.redis.redis-server" } - before do - allow(Dir).to receive(:glob).and_return([plist], []) - allow(Etc).to receive(:getlogin).and_return("igor") - allow(node).to receive(:[]).with("platform_version").and_return(platform_version) - cmd = "launchctl list #{service_label}" - allow(provider).to receive(:shell_out_with_systems_locale). - with(/(#{su_cmd} '#{cmd}'|#{cmd})/). - and_return(double("Status", - :stdout => launchctl_stdout, :exitstatus => 0)) - allow(File).to receive(:exists?).and_return([true], []) - allow(provider).to receive(:shell_out_with_systems_locale!). - with(/plutil -convert xml1 -o/). - and_return(double("Status", :stdout => plutil_stdout)) - end + let(:plist) { "/Library/LaunchDaemons/io.redis.redis-server.plist" } + let(:session) { StringIO.new } + if service_type == "Agent" + let(:plist) { "/Library/LaunchAgents/io.redis.redis-server.plist" } + let(:session) { "-S Aqua " } + let(:su_cmd) { "su -l igor -c" } + end + let(:service_label) { "io.redis.redis-server" } + before do + allow(run_context).to receive(:logger).and_return(logger) + allow(Dir).to receive(:glob).and_return([plist], []) + @stat = double("File::Stat", { uid: 501 }) + allow(File).to receive(:stat).and_return(@stat) + @getpwuid = double("Etc::Passwd", { name: "mikedodge04" }) + allow(Etc).to receive(:getpwuid).and_return(@getpwuid) + allow(node).to receive(:[]).with("platform_version").and_return("10.11.1") + cmd = "launchctl list #{service_label}" + allow(provider).to receive(:shell_out) + .with(/(#{su_cmd} '#{cmd}'|#{cmd})/, default_env: false) + .and_return(double("Status", + stdout: launchctl_stdout, exitstatus: 0)) + allow(File).to receive(:exist?).and_return([true], []) + allow(provider).to receive(:shell_out!) + .with(/plutil -convert xml1 -o/, default_env: false) + .and_return(double("Status", stdout: plutil_stdout)) + end - context "#{service_name} that is a #{service_type} running Osx #{platform_version}" do - let(:new_resource) { Chef::Resource::MacosxService.new(service_name) } - let!(:current_resource) { Chef::Resource::MacosxService.new(service_name) } + context "#{service_name} that is a #{service_type}" do + let(:new_resource) { Chef::Resource::MacosxService.new(service_name) } + let!(:current_resource) { Chef::Resource::MacosxService.new(service_name) } - describe "#load_current_resource" do + describe "#load_current_resource" do - # CHEF-5223 "you can't glob for a file that hasn't been converged - # onto the node yet." - context "when the plist doesn't exist" do + # CHEF-5223 "you can't glob for a file that hasn't been converged + # onto the node yet." + context "when the plist doesn't exist" do - def run_resource_setup_for_action(action) - new_resource.action(action) - provider.action = action - provider.load_current_resource - provider.define_resource_requirements - provider.process_resource_requirements - end + def run_resource_setup_for_action(action) + new_resource.action(action) + provider.action = action + provider.load_current_resource + provider.define_resource_requirements + provider.process_resource_requirements + end - before do - allow(Dir).to receive(:glob).and_return([]) - allow(File).to receive(:exists?).and_return([true], []) - allow(provider).to receive(:shell_out!). - with(/plutil -convert xml1 -o/). - and_raise(Mixlib::ShellOut::ShellCommandFailed) - end + before do + allow(Dir).to receive(:glob).and_return([]) + allow(File).to receive(:exist?).and_return([true], []) + allow(provider).to receive(:shell_out!) + .with(/plutil -convert xml1 -o/) + .and_raise(Mixlib::ShellOut::ShellCommandFailed) + end - it "works for action :nothing" do - expect { run_resource_setup_for_action(:nothing) }.not_to raise_error - end + it "works for action :nothing" do + expect { run_resource_setup_for_action(:nothing) }.not_to raise_error + end - it "works for action :start" do - expect { run_resource_setup_for_action(:start) }.not_to raise_error - end + it "works for action :start" do + expect { run_resource_setup_for_action(:start) }.not_to raise_error + end - it "errors if action is :enable" do - expect { run_resource_setup_for_action(:enable) }.to raise_error(Chef::Exceptions::Service) - end + it "errors if action is :enable" do + expect { run_resource_setup_for_action(:enable) }.to raise_error(Chef::Exceptions::Service) + end - it "errors if action is :disable" do - expect { run_resource_setup_for_action(:disable) }.to raise_error(Chef::Exceptions::Service) - end + it "errors if action is :disable" do + expect { run_resource_setup_for_action(:disable) }.to raise_error(Chef::Exceptions::Service) end + end - context "when launchctl returns pid in service list" do - let(:launchctl_stdout) { StringIO.new <<-SVC_LIST } -{ - "LimitLoadToSessionType" = "System"; - "Label" = "io.redis.redis-server"; - "TimeOut" = 30; - "OnDemand" = false; - "LastExitStatus" = 0; - "PID" = 62803; - "Program" = "do_some.sh"; - "ProgramArguments" = ( - "path/to/do_something.sh"; - "-f"; - ); -}; -SVC_LIST + context "when launchctl returns pid in service list" do + let(:launchctl_stdout) { StringIO.new <<~SVC_LIST } + { + "LimitLoadToSessionType" = "System"; + "Label" = "io.redis.redis-server"; + "TimeOut" = 30; + "OnDemand" = false; + "LastExitStatus" = 0; + "PID" = 62803; + "Program" = "do_some.sh"; + "ProgramArguments" = ( + "path/to/do_something.sh"; + "-f"; + ); + }; + SVC_LIST - before do - provider.load_current_resource - end + before do + provider.load_current_resource + end - it "sets resource running state to true" do - expect(provider.current_resource.running).to be_truthy - end + it "sets resource running state to true" do + expect(provider.current_resource.running).to be_truthy + end - it "sets resouce enabled state to true" do - expect(provider.current_resource.enabled).to be_truthy - end + it "sets resouce enabled state to true" do + expect(provider.current_resource.enabled).to be_truthy end + end - describe "running unsupported actions" do - before do - allow(Dir).to receive(:glob).and_return(["#{plist}"], []) - allow(File).to receive(:exists?).and_return([true], []) - end - it "should throw an exception when reload action is attempted" do - expect { provider.run_action(:reload) }.to raise_error(Chef::Exceptions::UnsupportedAction) - end + describe "running unsupported actions" do + before do + allow(Dir).to receive(:glob).and_return([(plist).to_s], []) + allow(File).to receive(:exist?).and_return([true], []) end - context "when launchctl returns empty service pid" do - let(:launchctl_stdout) { StringIO.new <<-SVC_LIST } -{ - "LimitLoadToSessionType" = "System"; - "Label" = "io.redis.redis-server"; - "TimeOut" = 30; - "OnDemand" = false; - "LastExitStatus" = 0; - "Program" = "do_some.sh"; - "ProgramArguments" = ( - "path/to/do_something.sh"; - "-f"; - ); -}; -SVC_LIST + it "should throw an exception when reload action is attempted" do + expect { provider.run_action(:reload) }.to raise_error(Chef::Exceptions::UnsupportedAction) + end + end + context "when launchctl returns empty service pid" do + let(:launchctl_stdout) { StringIO.new <<~SVC_LIST } + { + "LimitLoadToSessionType" = "System"; + "Label" = "io.redis.redis-server"; + "TimeOut" = 30; + "OnDemand" = false; + "LastExitStatus" = 0; + "Program" = "do_some.sh"; + "ProgramArguments" = ( + "path/to/do_something.sh"; + "-f"; + ); + }; + SVC_LIST - before do - provider.load_current_resource - end + before do + provider.load_current_resource + end - it "sets resource running state to false" do - expect(provider.current_resource.running).to be_falsey - end + it "sets resource running state to false" do + expect(provider.current_resource.running).to be_falsey + end - it "sets resouce enabled state to true" do - expect(provider.current_resource.enabled).to be_truthy - end + it "sets resouce enabled state to true" do + expect(provider.current_resource.enabled).to be_truthy end + end + + context "when launchctl doesn't return service entry at all" do + let(:launchctl_stdout) { StringIO.new <<~SVC_LIST } + Could not find service "io.redis.redis-server" in domain for system + SVC_LIST - context "when launchctl doesn't return service entry at all" do - let(:launchctl_stdout) { StringIO.new <<-SVC_LIST } -Could not find service "io.redis.redis-server" in domain for system -SVC_LIST + it "sets service running state to false" do + provider.load_current_resource + expect(provider.current_resource.running).to be_falsey + end - it "sets service running state to false" do + context "and plist for service is not available" do + before do + allow(Dir).to receive(:glob).and_return([]) provider.load_current_resource - expect(provider.current_resource.running).to be_falsey end - context "and plist for service is not available" do - before do - allow(Dir).to receive(:glob).and_return([]) - provider.load_current_resource - end - - it "sets resouce enabled state to false" do - expect(provider.current_resource.enabled).to be_falsey - end + it "sets resouce enabled state to false" do + expect(provider.current_resource.enabled).to be_falsey end + end - context "and plist for service is available" do - before do - allow(Dir).to receive(:glob).and_return(["#{plist}"], []) - provider.load_current_resource - end + context "and plist for service is available" do + before do + allow(Dir).to receive(:glob).and_return([(plist).to_s], []) + provider.load_current_resource + end - it "sets resouce enabled state to true" do - expect(provider.current_resource.enabled).to be_truthy - end + it "sets resouce enabled state to true" do + expect(provider.current_resource.enabled).to be_truthy end + end - describe "and several plists match service name" do - it "throws exception" do - allow(Dir).to receive(:glob).and_return(["#{plist}", - "/Users/wtf/something.plist"]) - provider.load_current_resource - provider.define_resource_requirements - expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service) - end + describe "and several plists match service name" do + it "throws exception" do + allow(Dir).to receive(:glob).and_return([(plist).to_s, + "/Users/wtf/something.plist"]) + provider.load_current_resource + provider.define_resource_requirements + expect { provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service) end end end - describe "#start_service" do - before do - allow(Chef::Resource::MacosxService).to receive(:new).and_return(current_resource) - provider.load_current_resource - allow(current_resource).to receive(:running).and_return(false) - end + end + describe "#start_service" do + before do + allow(Chef::Resource::MacosxService).to receive(:new).and_return(current_resource) + provider.load_current_resource + allow(current_resource).to receive(:running).and_return(false) + end - it "calls the start command if one is specified and service is not running" do - allow(new_resource).to receive(:start_command).and_return("cowsay dirty") + it "calls the start command if one is specified and service is not running" do + allow(new_resource).to receive(:start_command).and_return("cowsay dirty") - expect(provider).to receive(:shell_out_with_systems_locale!).with("cowsay dirty") - provider.start_service - end + expect(provider).to receive(:shell_out!).with("cowsay dirty", default_env: false) + provider.start_service + end - it "shows warning message if service is already running" do - allow(current_resource).to receive(:running).and_return(true) - expect(Chef::Log).to receive(:debug).with("macosx_service[#{service_name}] already running, not starting") + it "shows warning message if service is already running" do + allow(current_resource).to receive(:running).and_return(true) + expect(logger).to receive(:trace).with("macosx_service[#{service_name}] already running, not starting") - provider.start_service - end + provider.start_service + end - it "starts service via launchctl if service found" do - cmd = "launchctl load -w " + session + plist - expect(provider).to receive(:shell_out_with_systems_locale). - with(/(#{su_cmd} .#{cmd}.|#{cmd})/). - and_return(0) + it "starts service via launchctl if service found" do + cmd = "launchctl load -w " + session + plist + expect(provider).to receive(:shell_out) + .with(/(#{su_cmd} .#{cmd}.|#{cmd})/, default_env: false) + .and_return(0) - provider.start_service - end + provider.start_service end + end - describe "#stop_service" do - before do - allow(Chef::Resource::MacosxService).to receive(:new).and_return(current_resource) + describe "#stop_service" do + before do + allow(Chef::Resource::MacosxService).to receive(:new).and_return(current_resource) - provider.load_current_resource - allow(current_resource).to receive(:running).and_return(true) - end + provider.load_current_resource + allow(current_resource).to receive(:running).and_return(true) + end - it "calls the stop command if one is specified and service is running" do - allow(new_resource).to receive(:stop_command).and_return("kill -9 123") + it "calls the stop command if one is specified and service is running" do + allow(new_resource).to receive(:stop_command).and_return("kill -9 123") - expect(provider).to receive(:shell_out_with_systems_locale!).with("kill -9 123") - provider.stop_service - end + expect(provider).to receive(:shell_out!).with("kill -9 123", default_env: false) + provider.stop_service + end - it "shows warning message if service is not running" do - allow(current_resource).to receive(:running).and_return(false) - expect(Chef::Log).to receive(:debug).with("macosx_service[#{service_name}] not running, not stopping") + it "shows warning message if service is not running" do + allow(current_resource).to receive(:running).and_return(false) + expect(logger).to receive(:trace).with("macosx_service[#{service_name}] not running, not stopping") - provider.stop_service - end + provider.stop_service + end - it "stops the service via launchctl if service found" do - cmd = "launchctl unload -w " + plist - expect(provider).to receive(:shell_out_with_systems_locale). - with(/(#{su_cmd} .#{cmd}.|#{cmd})/). - and_return(0) + it "stops the service via launchctl if service found" do + cmd = "launchctl unload -w " + plist + expect(provider).to receive(:shell_out) + .with(/(#{su_cmd} .#{cmd}.|#{cmd})/, default_env: false) + .and_return(0) - provider.stop_service - end + provider.stop_service end + end - describe "#restart_service" do - before do - allow(Chef::Resource::Service).to receive(:new).and_return(current_resource) + describe "#restart_service" do + before do + allow(Chef::Resource::Service).to receive(:new).and_return(current_resource) - provider.load_current_resource - allow(current_resource).to receive(:running).and_return(true) - allow(provider).to receive(:sleep) - end + provider.load_current_resource + allow(current_resource).to receive(:running).and_return(true) + allow(provider).to receive(:sleep) + end - it "issues a command if given" do - allow(new_resource).to receive(:restart_command).and_return("reload that thing") + it "issues a command if given" do + allow(new_resource).to receive(:restart_command).and_return("reload that thing") - expect(provider).to receive(:shell_out_with_systems_locale!).with("reload that thing") - provider.restart_service - end + expect(provider).to receive(:shell_out!).with("reload that thing", default_env: false) + provider.restart_service + end - it "stops and then starts service" do - expect(provider).to receive(:unload_service) - expect(provider).to receive(:load_service); + it "stops and then starts service" do + expect(provider).to receive(:unload_service) + expect(provider).to receive(:load_service) - provider.restart_service - end + provider.restart_service end end end diff --git a/spec/unit/provider/service/openbsd_service_spec.rb b/spec/unit/provider/service/openbsd_service_spec.rb index 872a3bc400..dfa491fc38 100644 --- a/spec/unit/provider/service/openbsd_service_spec.rb +++ b/spec/unit/provider/service/openbsd_service_spec.rb @@ -31,11 +31,11 @@ end describe Chef::Provider::Service::Openbsd do let(:node) do node = Chef::Node.new - node.automatic_attrs[:command] = { :ps => "ps -ax" } + node.automatic_attrs[:command] = { ps: "ps -ax" } node end - let(:supports) { { :status => false } } + let(:supports) { { status: false } } let(:new_resource) do new_resource = Chef::Resource::Service.new("sndiod") @@ -93,7 +93,7 @@ describe Chef::Provider::Service::Openbsd do end context "when a status command has been specified" do - let(:status) { double(:stdout => "", :exitstatus => 0) } + let(:status) { double(stdout: "", exitstatus: 0) } before do new_resource.status_command("/bin/chefhasmonkeypants status") @@ -106,9 +106,9 @@ describe Chef::Provider::Service::Openbsd do end context "when the service supports status" do - let(:status) { double(:stdout => "", :exitstatus => 0) } + let(:status) { double(stdout: "", exitstatus: 0) } - let(:supports) { { :status => true } } + let(:supports) { { status: true } } it "should run '/etc/rc.d/service_name status'" do expect(provider).to receive(:shell_out).with("/etc/rc.d/#{new_resource.service_name} check").and_return(status) @@ -178,7 +178,8 @@ describe Chef::Provider::Service::Openbsd do [ %Q{thing_#{provider.builtin_service_enable_variable_name}="YES"}, %Q{#{provider.builtin_service_enable_variable_name}="NO"}, - ] end + ] + end it "sets enabled based on the exact match (false)" do provider.determine_enabled_status! expect(current_resource.enabled).to be false @@ -189,8 +190,9 @@ describe Chef::Provider::Service::Openbsd do let(:lines) do [ %Q{#{provider.builtin_service_enable_variable_name}_thing="YES"}, - %Q{#{provider.builtin_service_enable_variable_name}}, - ] end + (provider.builtin_service_enable_variable_name).to_s, + ] + end it "sets enabled based on the exact match (false)" do provider.determine_enabled_status! expect(current_resource.enabled).to be false @@ -202,7 +204,8 @@ describe Chef::Provider::Service::Openbsd do [ %Q{thing_#{provider.builtin_service_enable_variable_name}="NO"}, %Q{#{provider.builtin_service_enable_variable_name}="YES"}, - ] end + ] + end it "sets enabled based on the exact match (true)" do provider.determine_enabled_status! expect(current_resource.enabled).to be true @@ -214,7 +217,8 @@ describe Chef::Provider::Service::Openbsd do [ %Q{#{provider.builtin_service_enable_variable_name}_thing="NO"}, %Q{#{provider.builtin_service_enable_variable_name}="YES"}, - ] end + ] + end it "sets enabled based on the exact match (true)" do provider.determine_enabled_status! expect(current_resource.enabled).to be true @@ -285,26 +289,26 @@ describe Chef::Provider::Service::Openbsd do describe Chef::Provider::Service::Openbsd, "start_service" do it "should call the start command if one is specified" do new_resource.start_command("/etc/rc.d/chef startyousillysally") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/chef startyousillysally") - provider.start_service() + expect(provider).to receive(:shell_out!).with("/etc/rc.d/chef startyousillysally", default_env: false) + provider.start_service end it "should call '/usr/local/etc/rc.d/service_name start' if no start command is specified" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{new_resource.service_name} start") - provider.start_service() + expect(provider).to receive(:shell_out!).with("/etc/rc.d/#{new_resource.service_name} start", default_env: false) + provider.start_service end end describe Chef::Provider::Service::Openbsd, "stop_service" do it "should call the stop command if one is specified" do new_resource.stop_command("/etc/init.d/chef itoldyoutostop") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef itoldyoutostop") - provider.stop_service() + expect(provider).to receive(:shell_out!).with("/etc/init.d/chef itoldyoutostop", default_env: false) + provider.stop_service end it "should call '/usr/local/etc/rc.d/service_name stop' if no stop command is specified" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{new_resource.service_name} stop") - provider.stop_service() + expect(provider).to receive(:shell_out!).with("/etc/rc.d/#{new_resource.service_name} stop", default_env: false) + provider.stop_service end end @@ -312,21 +316,21 @@ describe Chef::Provider::Service::Openbsd do context "when the new_resource supports restart" do let(:supports) { { restart: true } } it "should call 'restart' on the service_name if the resource supports it" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/rc.d/#{new_resource.service_name} restart") - provider.restart_service() + expect(provider).to receive(:shell_out!).with("/etc/rc.d/#{new_resource.service_name} restart", default_env: false) + provider.restart_service end end it "should call the restart_command if one has been specified" do new_resource.restart_command("/etc/init.d/chef restartinafire") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/chef restartinafire") - provider.restart_service() + expect(provider).to receive(:shell_out!).with("/etc/init.d/chef restartinafire", default_env: false) + provider.restart_service end it "otherwise it should call stop and start" do expect(provider).to receive(:stop_service) expect(provider).to receive(:start_service) - provider.restart_service() + provider.restart_service end end end diff --git a/spec/unit/provider/service/redhat_spec.rb b/spec/unit/provider/service/redhat_spec.rb index 40f9bc3a91..d5d2c7ddc0 100644 --- a/spec/unit/provider/service/redhat_spec.rb +++ b/spec/unit/provider/service/redhat_spec.rb @@ -16,24 +16,24 @@ # limitations under the License. # -require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "spec_helper")) +require "spec_helper" require "ostruct" shared_examples_for "define_resource_requirements_common" do it "should raise an error if /sbin/chkconfig does not exist" do - allow(File).to receive(:exists?).with("/sbin/chkconfig").and_return(false) + allow(File).to receive(:exist?).with("/sbin/chkconfig").and_return(false) allow(@provider).to receive(:shell_out).with("/sbin/service chef status").and_raise(Errno::ENOENT) - allow(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_raise(Errno::ENOENT) + allow(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_raise(Errno::ENOENT) @provider.load_current_resource @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to 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 = double("Status", :exitstatus => 0, :stdout => "" , :stderr => "") + status = double("Status", exitstatus: 0, stdout: "" , stderr: "") expect(@provider).to receive(:shell_out).with("/sbin/service chef status").and_return(status) - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "", :stderr => "service chef supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add chef')") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "", stderr: "service chef supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add chef')") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) @provider.load_current_resource @provider.define_resource_requirements expect { @provider.process_resource_requirements }.not_to raise_error @@ -44,7 +44,7 @@ describe "Chef::Provider::Service::Redhat" do before(:each) do @node = Chef::Node.new - @node.automatic_attrs[:command] = { :ps => "foo" } + @node.automatic_attrs[:command] = { ps: "foo" } @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @@ -55,7 +55,7 @@ describe "Chef::Provider::Service::Redhat" do @provider = Chef::Provider::Service::Redhat.new(@new_resource, @run_context) @provider.action = :start allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource) - allow(File).to receive(:exists?).with("/sbin/chkconfig").and_return(true) + allow(File).to receive(:exist?).with("/sbin/chkconfig").and_return(true) end describe "while not in why run mode" do @@ -65,13 +65,13 @@ describe "Chef::Provider::Service::Redhat" do describe "load current resource" do before do - status = double("Status", :exitstatus => 0, :stdout => "" , :stderr => "") + status = double("Status", exitstatus: 0, stdout: "" , stderr: "") allow(@provider).to receive(:shell_out).with("/sbin/service chef status").and_return(status) end it "sets supports[:status] to true by default" do - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) expect(@provider.service_missing).to be false @provider.load_current_resource expect(@provider.supports[:status]).to be true @@ -80,9 +80,9 @@ describe "Chef::Provider::Service::Redhat" do it "lets the user override supports[:status] in the new_resource" do @new_resource.supports( { status: false } ) @new_resource.pattern "myservice" - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) - foo_out = double("ps_command", :exitstatus => 0, :stdout => "a line that matches myservice", :stderr => "") + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) + foo_out = double("ps_command", exitstatus: 0, stdout: "a line that matches myservice", stderr: "") expect(@provider).to receive(:shell_out!).with("foo").and_return(foo_out) expect(@provider.service_missing).to be false expect(@provider).not_to receive(:shell_out).with("/sbin/service chef status") @@ -91,16 +91,16 @@ describe "Chef::Provider::Service::Redhat" do end it "sets the current enabled status to true if the service is enabled for any run level" do - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:off 2:off 3:off 4:off 5:on 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) expect(@provider.service_missing).to be false @provider.load_current_resource expect(@current_resource.enabled).to be true end it "sets the current enabled status to false if the regex does not match" do - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:off 2:off 3:off 4:off 5:off 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:off 2:off 3:off 4:off 5:off 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) expect(@provider.service_missing).to be false expect(@provider.load_current_resource).to eql(@current_resource) expect(@current_resource.enabled).to be false @@ -108,8 +108,8 @@ describe "Chef::Provider::Service::Redhat" do it "sets the current enabled status to true if the service is enabled at specified run levels" do @new_resource.run_levels([1, 2]) - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:on 2:on 3:off 4:off 5:off 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:on 2:on 3:off 4:off 5:off 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) expect(@provider.service_missing).to be false @provider.load_current_resource expect(@current_resource.enabled).to be true @@ -118,8 +118,8 @@ describe "Chef::Provider::Service::Redhat" do it "sets the current enabled status to false if the service is enabled at a run level it should not" do @new_resource.run_levels([1, 2]) - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:on 2:on 3:on 4:off 5:off 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:on 2:on 3:on 4:off 5:off 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) expect(@provider.service_missing).to be false @provider.load_current_resource expect(@current_resource.enabled).to be false @@ -128,8 +128,8 @@ describe "Chef::Provider::Service::Redhat" do it "sets the current enabled status to false if the service is not enabled at specified run levels" do @new_resource.run_levels([ 2 ]) - chkconfig = double("Chkconfig", :exitstatus => 0, :stdout => "chef 0:off 1:on 2:off 3:off 4:off 5:off 6:off", :stderr => "") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", exitstatus: 0, stdout: "chef 0:off 1:on 2:off 3:off 4:off 5:off 6:off", stderr: "") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) expect(@provider.service_missing).to be false @provider.load_current_resource expect(@current_resource.enabled).to be false @@ -142,10 +142,10 @@ describe "Chef::Provider::Service::Redhat" do context "when the service does not exist" do before do - status = double("Status", :exitstatus => 1, :stdout => "", :stderr => "chef: unrecognized service") + status = double("Status", exitstatus: 1, stdout: "", stderr: "chef: unrecognized service") expect(@provider).to receive(:shell_out).with("/sbin/service chef status").and_return(status) - chkconfig = double("Chkconfig", :existatus => 1, :stdout => "", :stderr => "error reading information on service chef: No such file or directory") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", existatus: 1, stdout: "", stderr: "error reading information on service chef: No such file or directory") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) @provider.load_current_resource @provider.define_resource_requirements end @@ -194,10 +194,10 @@ describe "Chef::Provider::Service::Redhat" do it_should_behave_like "define_resource_requirements_common" it "should not raise an error if the service does not exist" do - status = double("Status", :exitstatus => 1, :stdout => "", :stderr => "chef: unrecognized service") + status = double("Status", exitstatus: 1, stdout: "", stderr: "chef: unrecognized service") expect(@provider).to receive(:shell_out).with("/sbin/service chef status").and_return(status) - chkconfig = double("Chkconfig", :existatus => 1, :stdout => "", :stderr => "error reading information on service chef: No such file or directory") - expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", :returns => [0, 1]).and_return(chkconfig) + chkconfig = double("Chkconfig", existatus: 1, stdout: "", stderr: "error reading information on service chef: No such file or directory") + expect(@provider).to receive(:shell_out!).with("/sbin/chkconfig --list chef", returns: [0, 1]).and_return(chkconfig) @provider.load_current_resource @provider.define_resource_requirements expect { @provider.process_resource_requirements }.not_to raise_error diff --git a/spec/unit/provider/service/simple_service_spec.rb b/spec/unit/provider/service/simple_service_spec.rb index 499e0cc2d3..2546f9cef7 100644 --- a/spec/unit/provider/service/simple_service_spec.rb +++ b/spec/unit/provider/service/simple_service_spec.rb @@ -21,7 +21,7 @@ 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" } + @node.automatic_attrs[:command] = { ps: "ps -ef" } @events = Chef::EventDispatch::Dispatcher.new @run_context = Chef::RunContext.new(@node, {}, @events) @@ -31,12 +31,12 @@ describe Chef::Provider::Service::Simple, "load_current_resource" do @provider = Chef::Provider::Service::Simple.new(@new_resource, @run_context) allow(Chef::Resource::Service).to receive(: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 = double("Status", :exitstatus => 0, :stdout => @stdout) + @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 = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out!).and_return(@status) end @@ -50,19 +50,19 @@ NOMOCKINGSTRINGSPLZ @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 } + it "should raise error if the node has a nil ps property and no other means to get status" do + @node.automatic_attrs[:command] = { ps: nil } @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to 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 => "" } + it "should raise error if the node has an empty ps property and no other means to get status" do + @node.automatic_attrs[:command] = { ps: "" } @provider.define_resource_requirements expect { @provider.process_resource_requirements }.to raise_error(Chef::Exceptions::Service) end - describe "when we have a 'ps' attribute" do + describe "when we have a 'ps' property" do it "should shell_out! the node's ps command" do expect(@provider).to receive(:shell_out!).with(@node[:command][:ps]).and_return(@status) @provider.load_current_resource @@ -75,11 +75,11 @@ NOMOCKINGSTRINGSPLZ 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 = double("Status", :exitstatus => 0, :stdout => @stdout) + @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 = double("Status", exitstatus: 0, stdout: @stdout) allow(@provider).to receive(:shell_out!).and_return(@status) @provider.load_current_resource expect(@current_resource.running).to be_truthy @@ -106,9 +106,9 @@ NOMOCKINGSTRINGSPLZ describe "when starting the service" do it "should call the start command if one is specified" do - allow(@new_resource).to receive(:start_command).and_return("#{@new_resource.start_command}") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("#{@new_resource.start_command}") - @provider.start_service() + @new_resource.start_command((@new_resource.start_command).to_s) + expect(@provider).to receive(:shell_out!).with((@new_resource.start_command).to_s, default_env: false) + @provider.start_service end it "should raise an exception if no start command is specified" do @@ -121,8 +121,8 @@ NOMOCKINGSTRINGSPLZ 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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/themadness stop") - @provider.stop_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/themadness stop", default_env: false) + @provider.stop_service end it "should raise an exception if no stop command is specified" do @@ -135,8 +135,8 @@ NOMOCKINGSTRINGSPLZ 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") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/etc/init.d/foo restart") - @provider.restart_service() + expect(@provider).to receive(:shell_out!).with("/etc/init.d/foo restart", default_env: false) + @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 @@ -149,7 +149,7 @@ NOMOCKINGSTRINGSPLZ expect(@provider).to receive(:stop_service) expect(@provider).to receive(:sleep).with(1) expect(@provider).to receive(:start_service) - @provider.restart_service() + @provider.restart_service end end @@ -162,8 +162,8 @@ NOMOCKINGSTRINGSPLZ it "should should run the user specified reload command if one is specified" do @new_resource.reload_command("kill -9 1") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("kill -9 1") - @provider.reload_service() + expect(@provider).to receive(:shell_out!).with("kill -9 1", default_env: false) + @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 index c6835bed64..9c44f727dc 100644 --- a/spec/unit/provider/service/solaris_smf_service_spec.rb +++ b/spec/unit/provider/service/solaris_smf_service_spec.rb @@ -1,6 +1,6 @@ # # Author:: Toomas Pelberg (<toomasp@gmx.net>) -# Copyright:: Copyright 2010-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -74,19 +74,19 @@ describe Chef::Provider::Service::Solaris do ].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 => "") + @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 => "") + @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 => "") + @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") + @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 => "") + @success = double("clear", exitstatus: 0, stdout: "", stdin: "", stderr: "") end it "should raise an error if /bin/svcs and /usr/sbin/svcadm are not executable" do @@ -116,18 +116,19 @@ describe Chef::Provider::Service::Solaris do describe "when discovering the current service state" do it "should create a current resource with the name of the new resource" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_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) + expect(@provider.maintenance).to be_falsey @provider.load_current_resource end it "should return the current resource" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_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(@enabled_svc_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 @@ -162,7 +163,7 @@ describe Chef::Provider::Service::Solaris do end it "should call svcadm enable -s chef" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status) + expect(@provider).to receive(:shell_out!).twice.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 @@ -172,7 +173,7 @@ describe Chef::Provider::Service::Solaris do end it "should call svcadm enable -s chef for start_service" do - expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status) + expect(@provider).to receive(:shell_out!).twice.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 @@ -182,7 +183,7 @@ describe Chef::Provider::Service::Solaris do it "should call svcadm clear chef for start_service when state maintenance" do # 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!).twice.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) @@ -191,20 +192,47 @@ describe Chef::Provider::Service::Solaris do 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) + 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 + describe "when enabling the service recursively" do + before(:each) do + @provider.current_resource = @current_resource + end + + it "should call svcadm enable -s -r chef" do + @new_resource.options("-r") + expect(@provider).to receive(:shell_out!).twice.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", "-r", @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 -r -t chef when passed an array of options" do + @new_resource.options(["-r", "-t"]) + expect(@provider).to receive(:shell_out!).twice.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", "-r", "-t", @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 + + end + describe "when disabling the service" do before(:each) do @provider.current_resource = @current_resource end it "should call svcadm disable -s chef" do - 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("/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 @@ -212,10 +240,19 @@ describe Chef::Provider::Service::Solaris do end it "should call svcadm disable -s chef for stop_service" do - 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("/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(@provider.disable_service).to be_truthy + expect(@current_resource.enabled).to be_falsey + end + + it "should call svcadm disable chef with options" do + @new_resource.options("-t") + 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", "-t", "chef").and_return(@success) + @provider.load_current_resource + expect(@provider.disable_service).to be_truthy expect(@current_resource.enabled).to be_falsey end @@ -224,7 +261,7 @@ describe Chef::Provider::Service::Solaris do describe "when reloading the service" do before(:each) do @provider.current_resource = @current_resource - allow(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status) + 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 @@ -237,7 +274,7 @@ describe Chef::Provider::Service::Solaris do describe "when the service doesn't exist" do before(:each) do @provider.current_resource = @current_resource - expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@no_svc_status) + 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 diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb index 4e25f499f6..34b8094974 100644 --- a/spec/unit/provider/service/systemd_service_spec.rb +++ b/spec/unit/provider/service/systemd_service_spec.rb @@ -1,7 +1,7 @@ # # Author:: Stephen Haynes (<sh@nomitor.com>) # Author:: Davide Cavalca (<dcavalca@fb.com>) -# Copyright:: Copyright 2011-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,39 +21,33 @@ require "spec_helper" describe Chef::Provider::Service::Systemd do - let(:node) do - node = Chef::Node.new - node.default["etc"] = Hash.new - node.default["etc"]["passwd"] = { - "joe" => { - "uid" => 10000, - }, - } - node - end + let(:node) { Chef::Node.new } let(:events) { Chef::EventDispatch::Dispatcher.new } let(:run_context) { Chef::RunContext.new(node, {}, events) } - let(:service_name) { "rsyslog.service" } + let(:service_name) { "rsyslog\\x2d.service" } + + let(:service_name_escaped) { "rsyslog\\\\x2d.service" } let(:new_resource) { Chef::Resource::Service.new(service_name) } let(:provider) { Chef::Provider::Service::Systemd.new(new_resource, run_context) } let(:shell_out_success) do - double("shell_out_with_systems_locale", :exitstatus => 0, :error? => false) + double("shell_out", exitstatus: 0, error?: false, stdout: "") end let(:shell_out_failure) do - double("shell_out_with_systems_locale", :exitstatus => 1, :error? => true) + double("shell_out", exitstatus: 1, error?: true, stdout: "") end let(:current_resource) { Chef::Resource::Service.new(service_name) } before(:each) do allow(Chef::Resource::Service).to receive(:new).with(service_name).and_return(current_resource) + allow(Etc).to receive(:getpwnam).and_return(OpenStruct.new(uid: 10000)) end describe "load_current_resource" do @@ -62,6 +56,7 @@ describe Chef::Provider::Service::Systemd do allow(provider).to receive(:is_active?).and_return(false) allow(provider).to receive(:is_enabled?).and_return(false) allow(provider).to receive(:is_masked?).and_return(false) + allow(provider).to receive(:is_indirect?).and_return(false) end it "should create a current resource with the name of the new resource" do @@ -176,19 +171,19 @@ describe Chef::Provider::Service::Systemd do it "should call the start command if one is specified" do allow(new_resource).to receive(:start_command).and_return("/sbin/rsyslog startyousillysally") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog startyousillysally") + expect(provider).to receive(:shell_out!).with("/sbin/rsyslog startyousillysally", default_env: false) provider.start_service end context "when a user is not specified" do it "should call '#{systemctl_path} --system start service_name' if no start command is specified" do - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system start #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "start", service_name, default_env: false, timeout: 900).and_return(shell_out_success) provider.start_service end it "should not call '#{systemctl_path} --system start service_name' if it is already running" do current_resource.running(true) - expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system start #{service_name}", {}) + expect(provider).not_to receive(:shell_out_compacted!).with(systemctl_path, "--system", "start", service_name, timeout: 900) provider.start_service end end @@ -196,14 +191,14 @@ describe Chef::Provider::Service::Systemd do context "when a user is specified" do it "should call '#{systemctl_path} --user start service_name' if no start command is specified" do current_resource.user("joe") - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --user start #{service_name}", { :environment => { "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/10000/bus" }, :user => "joe" }).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--user", "start", service_name, environment: { "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/10000/bus" }, user: "joe", default_env: false, timeout: 900).and_return(shell_out_success) provider.start_service end it "should not call '#{systemctl_path} --user start service_name' if it is already running" do current_resource.running(true) current_resource.user("joe") - expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --user start #{service_name}", { :environment => { "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/10000/bus" }, :user => "joe" }) + expect(provider).not_to receive(:shell_out_compacted!).with(systemctl_path, "--user", "start", service_name, environment: { "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/10000/bus" }, user: "joe", timeout: 900) provider.start_service end end @@ -211,13 +206,13 @@ describe Chef::Provider::Service::Systemd do it "should call the restart command if one is specified" do current_resource.running(true) allow(new_resource).to receive(:restart_command).and_return("/sbin/rsyslog restartyousillysally") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog restartyousillysally") + expect(provider).to receive(:shell_out!).with("/sbin/rsyslog restartyousillysally", default_env: false) provider.restart_service end it "should call '#{systemctl_path} --system restart service_name' if no restart command is specified" do current_resource.running(true) - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system restart #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "restart", service_name, default_env: false, timeout: 900).and_return(shell_out_success) provider.restart_service end @@ -226,7 +221,7 @@ describe Chef::Provider::Service::Systemd do it "should call the reload command" do current_resource.running(true) allow(new_resource).to receive(:reload_command).and_return("/sbin/rsyslog reloadyousillysally") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog reloadyousillysally") + expect(provider).to receive(:shell_out!).with("/sbin/rsyslog reloadyousillysally", default_env: false) provider.reload_service end end @@ -234,7 +229,7 @@ describe Chef::Provider::Service::Systemd do context "when a reload command is not specified" do it "should call '#{systemctl_path} --system reload service_name' if the service is running" do current_resource.running(true) - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system reload #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "reload", service_name, default_env: false, timeout: 900).and_return(shell_out_success) provider.reload_service end @@ -249,19 +244,19 @@ describe Chef::Provider::Service::Systemd do it "should call the stop command if one is specified" do current_resource.running(true) allow(new_resource).to receive(:stop_command).and_return("/sbin/rsyslog stopyousillysally") - expect(provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog stopyousillysally") + expect(provider).to receive(:shell_out!).with("/sbin/rsyslog stopyousillysally", default_env: false) provider.stop_service end it "should call '#{systemctl_path} --system stop service_name' if no stop command is specified" do current_resource.running(true) - expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system stop #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "stop", service_name, timeout: 900, default_env: false).and_return(shell_out_success) provider.stop_service end it "should not call '#{systemctl_path} --system stop service_name' if it is already stopped" do current_resource.running(false) - expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system stop #{service_name}", {}) + expect(provider).not_to receive(:shell_out_compacted!).with(systemctl_path, "--system", "stop", service_name, timeout: 900) provider.stop_service end end @@ -270,16 +265,16 @@ describe Chef::Provider::Service::Systemd do before(:each) do provider.current_resource = current_resource current_resource.service_name(service_name) - allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s) end it "should call '#{systemctl_path} --system enable service_name' to enable the service" do - expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system enable #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "enable", service_name, timeout: 900).and_return(shell_out_success) provider.enable_service end it "should call '#{systemctl_path} --system disable service_name' to disable the service" do - expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system disable #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "disable", service_name, timeout: 900).and_return(shell_out_success) provider.disable_service end end @@ -288,34 +283,92 @@ describe Chef::Provider::Service::Systemd do before(:each) do provider.current_resource = current_resource current_resource.service_name(service_name) - allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s) end it "should call '#{systemctl_path} --system mask service_name' to mask the service" do - expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system mask #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "mask", service_name, timeout: 900).and_return(shell_out_success) provider.mask_service end it "should call '#{systemctl_path} --system unmask service_name' to unmask the service" do - expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system unmask #{service_name}", {}).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted!).with(systemctl_path, "--system", "unmask", service_name, timeout: 900).and_return(shell_out_success) provider.unmask_service end end + enabled_and_active = <<-STDOUT + ActiveState=active + UnitFileState=enabled + STDOUT + disabled_and_inactive = <<-STDOUT + ActiveState=disabled + UnitFileState=inactive + STDOUT + # No unit known for this service, and inactive + nil_and_inactive = <<-STDOUT + ActiveState=inactive + UnitFileState= + STDOUT + + def with_systemctl_show(systemctl_path, stdout) + systemctl_show = [systemctl_path, "--system", "show", "-p", "UnitFileState", "-p", "ActiveState", service_name] + expect(provider).to receive(:shell_out!).with(*systemctl_show, {}).and_return(double(stdout: stdout, exitstatus: 0, error?: false)) + end + + describe "systemd_service_status" do + before(:each) do + provider.current_resource = current_resource + current_resource.service_name(service_name) + end + + it "should return status if '#{systemctl_path} --system show -p UnitFileState -p ActiveState service_name' returns 0 and has nil" do + nil_and_inactive_h = { + "ActiveState" => "inactive", + "UnitFileState" => nil, + } + with_systemctl_show(systemctl_path, nil_and_inactive) + expect(provider.systemd_service_status).to eql(nil_and_inactive_h) + end + + it "should error if '#{systemctl_path} --system show -p UnitFileState -p ActiveState service_name' misses fields" do + partial_systemctl_stdout = <<-STDOUT + ActiveState=inactive + STDOUT + with_systemctl_show(systemctl_path, partial_systemctl_stdout) + expect { provider.systemd_service_status }.to raise_error(Chef::Exceptions::Service) + end + + it "should error if '#{systemctl_path} --system show -p UnitFileState -p ActiveState service_name' returns non 0" do + systemctl_show = [systemctl_path, "--system", "show", "-p", "UnitFileState", "-p", "ActiveState", service_name] + allow(provider).to receive(:shell_out!).with(*systemctl_show, {}).and_return(shell_out_failure) + expect { provider.systemd_service_status }.to raise_error(Chef::Exceptions::Service) + end + end + describe "is_active?" do before(:each) do provider.current_resource = current_resource current_resource.service_name(service_name) - allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s) end - it "should return true if '#{systemctl_path} --system is-active service_name' returns 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-active #{service_name} --quiet", {}).and_return(shell_out_success) + it "should return true if service is active" do + with_systemctl_show(systemctl_path, enabled_and_active) expect(provider.is_active?).to be true end - it "should return false if '#{systemctl_path} --system is-active service_name' returns anything except 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-active #{service_name} --quiet", {}).and_return(shell_out_failure) + it "should return false if service is not active" do + with_systemctl_show(systemctl_path, disabled_and_inactive) + expect(provider.is_active?).to be false + end + + it "should return false if service is activating" do + enabled_and_activating = <<-STDOUT + ActiveState=activating + UnitFileState=enabled + STDOUT + with_systemctl_show(systemctl_path, enabled_and_activating) expect(provider.is_active?).to be false end end @@ -324,16 +377,39 @@ describe Chef::Provider::Service::Systemd do before(:each) do provider.current_resource = current_resource current_resource.service_name(service_name) - allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s) + end + + it "should return true if service is enabled" do + with_systemctl_show(systemctl_path, enabled_and_active) + expect(provider.is_enabled?).to be true + end + + it "should return false if service is disabled" do + with_systemctl_show(systemctl_path, disabled_and_inactive) + expect(provider.is_enabled?).to be false end - it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name} --quiet", {}).and_return(shell_out_success) + it "should return false if service has no unit file" do + with_systemctl_show(systemctl_path, nil_and_inactive) + expect(provider.is_enabled?).to be false + end + + it "should return true if service is static" do + static_and_active = <<-STDOUT + ActiveState=active + UnitFileState=static + STDOUT + with_systemctl_show(systemctl_path, static_and_active) expect(provider.is_enabled?).to be true end - it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name} --quiet", {}).and_return(shell_out_failure) + it "should return false if service is enabled-runtime" do + enabled_runtime_and_active = <<-STDOUT + ActiveState=active + UnitFileState=enabled-runtime + STDOUT + with_systemctl_show(systemctl_path, enabled_runtime_and_active) expect(provider.is_enabled?).to be false end end @@ -342,29 +418,64 @@ describe Chef::Provider::Service::Systemd do before(:each) do provider.current_resource = current_resource current_resource.service_name(service_name) - allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}") + allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s) end - it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 'masked' and returns anything except 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "masked", :exitstatus => shell_out_failure)) + it "should return true if service is masked" do + masked_and_inactive = <<-STDOUT + ActiveState=inactive + UnitFileState=masked + STDOUT + with_systemctl_show(systemctl_path, masked_and_inactive) expect(provider.is_masked?).to be true end - it "should return true if '#{systemctl_path} --system is-enabled service_name' outputs 'masked-runtime' and returns anything except 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "masked-runtime", :exitstatus => shell_out_failure)) - expect(provider.is_masked?).to be true + it "should return false if service is masked-runtime" do + masked_runtime_and_inactive = <<-STDOUT + ActiveState=inactive + UnitFileState=masked-runtime + STDOUT + with_systemctl_show(systemctl_path, masked_runtime_and_inactive) + expect(provider.is_masked?).to be false end - it "should return false if '#{systemctl_path} --system is-enabled service_name' returns 0" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "enabled", :exitstatus => shell_out_success)) + it "should return false if service is enabled" do + with_systemctl_show(systemctl_path, enabled_and_active) expect(provider.is_masked?).to be false end - it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0 and outputs an error'" do - expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "Failed to get unit file state for #{service_name}: No such file or directory", :exitstatus => shell_out_failure)) + it "should return false if service has no known unit file" do + with_systemctl_show(systemctl_path, nil_and_inactive) expect(provider.is_masked?).to be false end end + + describe "is_indirect?" do + before(:each) do + provider.current_resource = current_resource + current_resource.service_name(service_name) + allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s) + end + + it "should return true if service is indirect" do + indirect_and_inactive = <<-STDOUT + ActiveState=inactive + UnitFileState=indirect + STDOUT + with_systemctl_show(systemctl_path, indirect_and_inactive) + expect(provider.is_indirect?).to be true + end + + it "should return false if service not indirect" do + with_systemctl_show(systemctl_path, enabled_and_active) + expect(provider.is_indirect?).to be false + end + + it "should return false if service has no known unit file" do + with_systemctl_show(systemctl_path, nil_and_inactive) + expect(provider.is_indirect?).to be false + end + end end end end diff --git a/spec/unit/provider/service/upstart_service_spec.rb b/spec/unit/provider/service/upstart_service_spec.rb index fb5a418684..20cbef11ce 100644 --- a/spec/unit/provider/service/upstart_service_spec.rb +++ b/spec/unit/provider/service/upstart_service_spec.rb @@ -20,7 +20,7 @@ require "spec_helper" describe Chef::Provider::Service::Upstart do let(:shell_out_success) do - double("shell_out_with_systems_locale", :exitstatus => 0, :error? => false) + double("shell_out", exitstatus: 0, error?: false) end before(:each) do @@ -43,7 +43,7 @@ describe Chef::Provider::Service::Upstart do 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" ]) + # Chef::Platform.stub(:find_platform_and_version).and_return([ "ubuntu", "9.04" ]) @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context) expect(@provider.instance_variable_get(:@upstart_job_dir)).to eq("/etc/event.d") expect(@provider.instance_variable_get(:@upstart_conf_suffix)).to eq("") @@ -66,19 +66,15 @@ describe Chef::Provider::Service::Upstart do describe "load_current_resource" do before(:each) do - @node.automatic_attrs[:command] = { :ps => "ps -ax" } + @node.automatic_attrs[:command] = { ps: "ps -ax" } @current_resource = Chef::Resource::Service.new("rsyslog") allow(Chef::Resource::Service).to receive(:new).and_return(@current_resource) - @status = double("Status", :exitstatus => 0) - allow(@provider).to receive(:popen4).and_return(@status) - @stdin = StringIO.new - @stdout = StringIO.new - @stderr = StringIO.new - @pid = double("PID") + @status = double("Status", exitstatus: 0, stdout: "", stderr: "") + allow(@provider).to receive(:shell_out).and_return(@status) - allow(::File).to receive(:exists?).and_return(true) + allow(::File).to receive(:exist?).and_return(true) allow(::File).to receive(:open).and_return(true) end @@ -100,28 +96,25 @@ describe Chef::Provider::Service::Upstart do end it "should run '/sbin/status rsyslog'" do - expect(@provider).to receive(:popen4).with("/sbin/status rsyslog").and_return(@status) + expect(@provider).to receive(:shell_out).with("/sbin/status rsyslog").and_return(@status) @provider.load_current_resource end describe "when the status command uses the new format" do it "should set running to true if the goal state is 'start'" do - @stdout = StringIO.new("rsyslog start/running") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog start/running") @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to true if the goal state is 'start' but current state is not 'running'" do - @stdout = StringIO.new("rsyslog start/starting") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog start/starting") @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to false if the goal state is 'stop'" do - @stdout = StringIO.new("rsyslog stop/waiting") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog stop/waiting") @provider.load_current_resource expect(@current_resource.running).to be_falsey end @@ -129,22 +122,19 @@ describe Chef::Provider::Service::Upstart do describe "when the status command uses the new format with an instance" do it "should set running to true if the goal state is 'start'" do - @stdout = StringIO.new("rsyslog (test) start/running, process 100") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog (test) start/running, process 100") @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to true if the goal state is 'start' but current state is not 'running'" do - @stdout = StringIO.new("rsyslog (test) start/starting, process 100") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog (test) start/starting, process 100") @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to false if the goal state is 'stop'" do - @stdout = StringIO.new("rsyslog (test) stop/waiting, process 100") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog (test) stop/waiting, process 100") @provider.load_current_resource expect(@current_resource.running).to be_falsey end @@ -152,22 +142,19 @@ describe Chef::Provider::Service::Upstart do describe "when the status command uses the old format" do it "should set running to true if the goal state is 'start'" do - @stdout = StringIO.new("rsyslog (start) running, process 32225") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog (start) running, process 32225") @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to true if the goal state is 'start' but current state is not 'running'" do - @stdout = StringIO.new("rsyslog (start) starting, process 32225") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog (start) starting, process 32225") @provider.load_current_resource expect(@current_resource.running).to be_truthy end it "should set running to false if the goal state is 'stop'" do - @stdout = StringIO.new("rsyslog (stop) waiting") - allow(@provider).to receive(:popen4).and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status) + expect(@status).to receive(:stdout).and_return("rsyslog (stop) waiting") @provider.load_current_resource expect(@current_resource.running).to be_falsey end @@ -180,34 +167,34 @@ describe Chef::Provider::Service::Upstart do end it "should set enabled to true when it finds 'starts on'" do - @lines = double("start on filesystem", :gets => "start on filesystem") + @lines = double("start on filesystem", gets: "start on filesystem") allow(::File).to receive(:open).and_yield(@lines) expect(@current_resource).to receive(:running).with(false) @provider.load_current_resource end it "should set enabled to false when it finds '#starts on'" do - @lines = double("start on filesystem", :gets => "#start on filesystem") + @lines = double("start on filesystem", gets: "#start on filesystem") allow(::File).to receive(:open).and_yield(@lines) expect(@current_resource).to receive(:running).with(false) @provider.load_current_resource end it "should assume disable when no job configuration file is found" do - allow(::File).to receive(:exists?).and_return(false) + allow(::File).to receive(:exist?).and_return(false) expect(@current_resource).to receive(:running).with(false) @provider.load_current_resource end it "should track state when the upstart configuration file fails to load" do - expect(File).to receive(:exists?).and_return false + expect(File).to receive(:exist?).and_return false @provider.load_current_resource expect(@provider.instance_variable_get("@config_file_found")).to eq(false) end describe "when a status command has been specified" do before do - allow(@new_resource).to receive(:status_command).and_return("/bin/chefhasmonkeypants status") + @new_resource.status_command("/bin/chefhasmonkeypants status") end it "should run the services status command if one has been specified" do @@ -255,7 +242,7 @@ describe Chef::Provider::Service::Upstart do allow(@current_resource).to receive(:enabled).and_return(false) expect(@file).to receive(:search_file_replace) expect(@file).to receive(:write_file) - @provider.enable_service() + @provider.enable_service end it "should disable the service if it is enabled" do @@ -264,7 +251,7 @@ describe Chef::Provider::Service::Upstart do allow(@current_resource).to receive(:enabled).and_return(true) expect(@file).to receive(:search_file_replace) expect(@file).to receive(:write_file) - @provider.disable_service() + @provider.disable_service end end @@ -278,20 +265,22 @@ describe Chef::Provider::Service::Upstart do end it "should call the start command if one is specified" do - allow(@new_resource).to receive(:start_command).and_return("/sbin/rsyslog startyousillysally") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog startyousillysally") - @provider.start_service() + @provider.upstart_service_running = false + @new_resource.start_command("/sbin/rsyslog startyousillysally") + expect(@provider).to receive(:shell_out!).with("/sbin/rsyslog startyousillysally", default_env: false) + @provider.start_service end it "should call '/sbin/start service_name' if no start command is specified" do - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/start #{@new_resource.service_name}").and_return(shell_out_success) - @provider.start_service() + @provider.upstart_service_running = false + expect(@provider).to receive(:shell_out!).with("/sbin/start #{@new_resource.service_name}", default_env: false).and_return(shell_out_success) + @provider.start_service end it "should not call '/sbin/start service_name' if it is already running" do - allow(@current_resource).to receive(:running).and_return(true) - expect(@provider).not_to receive(:shell_out_with_systems_locale!) - @provider.start_service() + @provider.upstart_service_running = true + expect(@provider).not_to receive(:shell_out!) + @provider.start_service end it "should pass parameters to the start command if they are provided" do @@ -299,59 +288,64 @@ describe Chef::Provider::Service::Upstart do @new_resource.parameters({ "OSD_ID" => "2" }) @provider = Chef::Provider::Service::Upstart.new(@new_resource, @run_context) @provider.current_resource = @current_resource - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/start rsyslog OSD_ID=2").and_return(shell_out_success) - @provider.start_service() + expect(@provider).to receive(:shell_out!).with("/sbin/start rsyslog OSD_ID=2", default_env: false).and_return(shell_out_success) + @provider.start_service end it "should call the restart command if one is specified" do allow(@current_resource).to receive(:running).and_return(true) - allow(@new_resource).to receive(:restart_command).and_return("/sbin/rsyslog restartyousillysally") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog restartyousillysally") - @provider.restart_service() + @new_resource.restart_command("/sbin/rsyslog restartyousillysally") + expect(@provider).to receive(:shell_out!).with("/sbin/rsyslog restartyousillysally", default_env: false) + @provider.restart_service end - it "should call '/sbin/restart service_name' if no restart command is specified" do - allow(@current_resource).to receive(:running).and_return(true) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/restart #{@new_resource.service_name}").and_return(shell_out_success) - @provider.restart_service() + it "should call start/sleep/stop if no restart command is specified" do + @provider.upstart_service_running = true + expect(@provider).to receive(:stop_service) + expect(@provider).to receive(:sleep).with(1) + expect(@provider).to receive(:start_service) + @provider.restart_service end it "should call '/sbin/start service_name' if restart_service is called for a stopped service" do + @provider.upstart_service_running = false allow(@current_resource).to receive(:running).and_return(false) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/start #{@new_resource.service_name}").and_return(shell_out_success) - @provider.restart_service() + expect(@provider).to receive(:shell_out!).with("/sbin/start #{@new_resource.service_name}", default_env: false).and_return(shell_out_success) + @provider.restart_service end it "should call the reload command if one is specified" do allow(@current_resource).to receive(:running).and_return(true) - allow(@new_resource).to receive(:reload_command).and_return("/sbin/rsyslog reloadyousillysally") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog reloadyousillysally") - @provider.reload_service() + @new_resource.reload_command("/sbin/rsyslog reloadyousillysally") + expect(@provider).to receive(:shell_out!).with("/sbin/rsyslog reloadyousillysally", default_env: false) + @provider.reload_service end it "should call '/sbin/reload service_name' if no reload command is specified" do allow(@current_resource).to receive(:running).and_return(true) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/reload #{@new_resource.service_name}").and_return(shell_out_success) - @provider.reload_service() + expect(@provider).to receive(:shell_out!).with("/sbin/reload #{@new_resource.service_name}", default_env: false).and_return(shell_out_success) + @provider.reload_service end it "should call the stop command if one is specified" do - allow(@current_resource).to receive(:running).and_return(true) - allow(@new_resource).to receive(:stop_command).and_return("/sbin/rsyslog stopyousillysally") - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/rsyslog stopyousillysally") - @provider.stop_service() + @provider.upstart_service_running = true + @new_resource.stop_command("/sbin/rsyslog stopyousillysally") + expect(@provider).to receive(:shell_out!).with("/sbin/rsyslog stopyousillysally", default_env: false) + @provider.stop_service end it "should call '/sbin/stop service_name' if no stop command is specified" do - allow(@current_resource).to receive(:running).and_return(true) - expect(@provider).to receive(:shell_out_with_systems_locale!).with("/sbin/stop #{@new_resource.service_name}").and_return(shell_out_success) - @provider.stop_service() + @provider.upstart_service_running = true + expect(@provider).to receive(:shell_out!).with("/sbin/stop #{@new_resource.service_name}", default_env: false).and_return(shell_out_success) + @provider.stop_service end it "should not call '/sbin/stop service_name' if it is already stopped" do + @provider.upstart_service_running = false allow(@current_resource).to receive(:running).and_return(false) - expect(@provider).not_to receive(:shell_out_with_systems_locale!).with("/sbin/stop #{@new_resource.service_name}") - @provider.stop_service() + expect(@provider).not_to receive(:shell_out!).with("/sbin/stop #{@new_resource.service_name}", default_env: false) + @provider.stop_service + expect(@upstart_service_running).to be_falsey end end end diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb index d4c451511d..b3a85715a8 100644 --- a/spec/unit/provider/service/windows_spec.rb +++ b/spec/unit/provider/service/windows_spec.rb @@ -1,7 +1,7 @@ # # Author:: Nuo Yan <nuo@chef.io> # Author:: Seth Chisamore <schisamo@chef.io> -# Copyright:: Copyright 2010-2016, Chef Software Inc. +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,18 +18,75 @@ # require "spec_helper" -require "mixlib/shellout" describe Chef::Provider::Service::Windows, "load_current_resource" do include_context "Win32" - let(:new_resource) { Chef::Resource::WindowsService.new("chef") } + before do + stub_const("Chef::ReservedNames::Win32::Security", Class.new) unless windows? + end + + let(:logger) { double("Mixlib::Log::Child").as_null_object } + + let(:chef_service_name) { "chef-client" } + let(:new_resource) { Chef::Resource::WindowsService.new(chef_service_name) } + + # Actual response from Win32::Service.config_info('chef-client') + let(:chef_service_binary_path_name) do + 'C:\\opscode\\chef\\embedded\\bin\\ruby.exe C:\\opscode\\chef\\bin\\chef-windows-service' + end + let(:chef_service_config_info) do + double("Struct::ServiceConfigInfo", + service_type: "own process", + start_type: "auto start", + error_control: "ignore", + binary_path_name: chef_service_binary_path_name, + load_order_group: "", + tag_id: 0, + dependencies: ["Winmgmt"], + service_start_name: "LocalSystem", + display_name: "Chef Client Service") + end + + # Actual response from Win32::Service.services + let(:chef_service_info) do + double("Struct::ServiceInfo", + service_name: chef_service_name, + display_name: "Chef Client Service", + service_type: "own process", + current_state: "running", + controls_accepted: [], + win32_exit_code: 1077, + service_specific_exit_code: 0, + check_point: 0, + wait_hint: 0, + binary_path_name: chef_service_binary_path_name, + start_type: "auto start", + error_control: "ignore", + load_order_group: "", + tag_id: 0, + start_name: "LocalSystem", + dependencies: ["Winmgmt"], + description: "Runs Chef Client on regular, configurable intervals.", + interactive: false, + pid: 0, + service_flags: 0, + reset_period: 0, + reboot_message: nil, + command: nil, + num_actions: 0, + actions: nil, + delayed_start: 1) + end + let(:provider) do - prvdr = Chef::Provider::Service::Windows.new(new_resource, - Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)) + run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new) + allow(run_context).to receive(:logger).and_return(logger) + prvdr = Chef::Provider::Service::Windows.new(new_resource, run_context) prvdr.current_resource = Chef::Resource::WindowsService.new("current-chef") prvdr end + let(:service_right) { Chef::Provider::Service::Windows::SERVICE_RIGHT } before(:all) do @@ -41,13 +98,18 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do Win32::Service::DEMAND_START = 0x00000003 Win32::Service::DISABLED = 0x00000004 + allow(Win32::Service).to receive(:start).with(any_args).and_return(Win32::Service) allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "running")) - allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "auto start")) + double("StatusStruct", current_state: "running") + ) + allow(Win32::Service).to receive(:config_info).with(new_resource.service_name) + .and_return(chef_service_config_info) + + allow(Win32::Service).to receive(:delayed_start).with(chef_service_name).and_return(1) allow(Win32::Service).to receive(:exists?).and_return(true) allow(Win32::Service).to receive(:configure).and_return(Win32::Service) allow(Chef::ReservedNames::Win32::Security).to receive(:get_account_right).and_return([]) + allow(Chef::ReservedNames::Win32::Security).to receive(:add_account_right).with("localsystem", "SeServiceLogonRight").and_return(0) end after(:each) do @@ -58,121 +120,563 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do it "sets the current resources service name to the new resources service name" do provider.load_current_resource - expect(provider.current_resource.service_name).to eq("chef") + expect(provider.current_resource.service_name).to eq(chef_service_name) end it "returns the current resource" do expect(provider.load_current_resource).to equal(provider.current_resource) end - it "sets the current resources status" do - provider.load_current_resource - expect(provider.current_resource.running).to be_truthy - end - it "sets the current resources start type" do provider.load_current_resource expect(provider.current_resource.enabled).to be_truthy end - it "does not set the current resources start type if it is neither AUTO START or DISABLED" do - allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "manual")) - provider.load_current_resource - expect(provider.current_resource.enabled).to be_nil + context "service does not exist" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false) + end + + %w{running enabled startup_type error_control binary_path_name + load_order_group dependencies run_as_user display_name }.each do |prop| + it "does not set #{prop}" do + expect(provider.current_resource.running).to be_nil + end + end + end + + context "service exists" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true) + allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( + double("Struct::ServiceConfigInfo", + service_type: "share process", + start_type: "demand start", + error_control: "normal", + binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted', + load_order_group: "TDI", + tag_id: 0, + dependencies: %w{NSI Tdx Afd}, + service_start_name: 'NT Authority\\LocalService', + display_name: "DHCP Client") + ) + end + + context "startup_type is neither :automatic or :disabled" do + before do + allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( + double("Struct::ServiceConfigInfo", + service_type: "share process", + start_type: "demand start", + error_control: "normal", + binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted', + load_order_group: "TDI", + tag_id: 0, + dependencies: %w{NSI Tdx Afd}, + service_start_name: 'NT Authority\\LocalService', + display_name: "DHCP Client") + ) + end + + it "does not set the current resources enabled" do + provider.load_current_resource + expect(provider.current_resource.enabled).to be_nil + end + end + + it "sets the current resources running to true if it's running" do + allow(provider).to receive(:current_state).and_return("running") + provider.load_current_resource + expect(provider.current_resource.running).to be true + end + + it "sets the current resources running to false if it's in any other state" do + allow(provider).to receive(:current_state).and_return("other state") + provider.load_current_resource + expect(provider.current_resource.running).to be false + end + + it "sets startup_type" do + expect(provider.current_resource.startup_type).to be_truthy + end + + it "sets error_control" do + provider.load_current_resource + expect(provider.current_resource.error_control).to be_truthy + end + + it "sets binary_path_name" do + provider.load_current_resource + expect(provider.current_resource.binary_path_name).to be_truthy + end + + it "sets load_order_group" do + provider.load_current_resource + expect(provider.current_resource.load_order_group).to be_truthy + end + + it "sets dependencies" do + provider.load_current_resource + expect(provider.current_resource.dependencies).to be_truthy + end + + it "sets run_as_user" do + provider.load_current_resource + expect(provider.current_resource.run_as_user).to be_truthy + end + + it "sets display_name" do + provider.load_current_resource + expect(provider.current_resource.display_name).to be_truthy + end + + it "sets delayed start to true if delayed start is enabled" do + allow(Win32::Service).to receive(:delayed_start).with(chef_service_name).and_return(1) + provider.load_current_resource + expect(provider.current_resource.delayed_start).to be true + end + + it "sets delayed start to false if delayed start is disabled" do + allow(Win32::Service).to receive(:delayed_start).with(chef_service_name).and_return(0) + provider.load_current_resource + expect(provider.current_resource.delayed_start).to be false + end + end + + describe Chef::Provider::Service::Windows, "action_create" do + before do + provider.new_resource.binary_path_name = chef_service_binary_path_name + end + + context "service exists" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true) + end + + it "logs debug message" do + expect(logger).to receive(:trace).with("windows_service[#{chef_service_name}] already exists - nothing to do") + provider.action_create + end + + it "does not converge" do + provider.action_create + expect(provider.resource_updated?).to be false + end + + it "does not create service" do + expect(Win32::Service).to_not receive(:new) + provider.action_create + end + + it "does not call converge_delayed_start" do + expect(provider).to_not receive(:converge_delayed_start) + provider.action_create + end + end + + context "service does not exist" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false) + allow(Win32::Service).to receive(:new).with(anything).and_return(true) + end + + it "converges resource" do + provider.action_create + expect(provider.resource_updated?).to be true + end + + it "creates service" do + expect(Win32::Service).to receive(:new) + provider.action_create + end + + it "creates service with correct configuration" do + expect(Win32::Service).to receive(:new).with( + service_name: chef_service_name, + service_type: 16, + start_type: 2, + error_control: 1, + binary_path_name: chef_service_binary_path_name, + service_start_name: "localsystem", + desired_access: 983551 + ) + provider.action_create + end + + it "calls converge_delayed_start" do + expect(provider).to receive(:converge_delayed_start) + provider.action_create + end + end + end + + describe Chef::Provider::Service::Windows, "action_delete" do + context "service exists" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true) + allow(Win32::Service).to receive(:delete).with(chef_service_name).and_return(true) + end + + it "converges resource" do + provider.action_delete + expect(provider.resource_updated?).to be true + end + + it "deletes service" do + expect(Win32::Service).to receive(:delete).with(chef_service_name) + provider.action_delete + end + end + + context "service does not exist" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false) + end + + it "logs debug message" do + expect(logger).to receive(:trace).with("windows_service[#{chef_service_name}] does not exist - nothing to do") + provider.action_delete + end + + it "does not converge" do + provider.action_delete + expect(provider.resource_updated?).to be false + end + + it "does not delete service" do + expect(Win32::Service).to_not receive(:delete) + provider.action_delete + end + end + end + + describe Chef::Provider::Service::Windows, "action_configure" do + context "service exists" do + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true) + allow(Win32::Service).to receive(:configure).with(anything).and_return(true) + end + + # properties that are Strings + %i{binary_path_name load_order_group dependencies run_as_user + display_name description}.each do |attr| + it "configures service if #{attr} has changed" do + provider.current_resource.send("#{attr}=", "old value") + provider.new_resource.send("#{attr}=", "new value") + + expect(Win32::Service).to receive(:configure) + provider.action_configure + end + end + + # properties that are Integers + %i{service_type error_control}.each do |attr| + it "configures service if #{attr} has changed" do + provider.current_resource.send("#{attr}=", 1) + provider.new_resource.send("#{attr}=", 2) + + expect(Win32::Service).to receive(:configure) + provider.action_configure + end + end + + it "configures service if startup_type has changed" do + provider.current_resource.startup_type = :automatic + provider.new_resource.startup_type = :manual + + expect(Win32::Service).to receive(:configure) + provider.action_configure + end + + it "does not configure service when run_as_user case is different" do + provider.current_resource.run_as_user = "JohnDoe" + provider.new_resource.run_as_user = "johndoe" + expect(Win32::Service).not_to receive(:configure) + provider.action_configure + + provider.current_resource.run_as_user = "johndoe" + provider.new_resource.run_as_user = "JohnDoe" + expect(Win32::Service).not_to receive(:configure) + provider.action_configure + end + + it "calls converge_delayed_start" do + expect(provider).to receive(:converge_delayed_start) + provider.action_configure + end + end + + context "service does not exist" do + let(:missing_service_warning_message) { "windows_service[#{chef_service_name}] does not exist. Maybe you need to prepend action :create" } + + before do + allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false) + + # This prevents warnings being logged during unit tests which adds to + # developer confusion when they aren't familiar with this specific test + allow(logger).to receive(:warn).with(missing_service_warning_message) + end + + it "logs warning" do + expect(logger).to receive(:warn).with(missing_service_warning_message) + provider.action_configure + end + + it "does not converge" do + provider.action_configure + expect(provider.resource_updated?).to be false + end + + it "does not configure service" do + expect(Win32::Service).to_not receive(:configure) + provider.action_configure + end + + it "does not call converge_delayed_start" do + expect(provider).to_not receive(:converge_delayed_start) + provider.action_configure + end + end + end + + describe Chef::Provider::Service::Windows, "converge_delayed_start" do + before do + allow(Win32::Service).to receive(:configure).and_return(true) + end + + context "delayed start needs to be updated" do + before do + provider.current_resource.delayed_start = false + provider.new_resource.delayed_start = true + end + + it "configures delayed start" do + expect(Win32::Service).to receive(:configure) + provider.send(:converge_delayed_start) + end + + it "configures delayed start with correct params" do + expect(Win32::Service).to receive(:configure).with(service_name: chef_service_name, delayed_start: 1) + provider.send(:converge_delayed_start) + end + + it "converges resource" do + provider.send(:converge_delayed_start) + expect(provider.resource_updated?).to be true + end + end + + context "delayed start does not need to be updated" do + before do + provider.current_resource.delayed_start = false + provider.new_resource.delayed_start = false + end + + it "does not configure delayed start" do + expect(Win32::Service).to_not receive(:configure) + provider.send(:converge_delayed_start) + end + + it "does not converge" do + provider.send(:converge_delayed_start) + expect(provider.resource_updated?).to be false + end + end end describe Chef::Provider::Service::Windows, "start_service" do before(:each) do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "stopped"), - double("StatusStruct", :current_state => "running")) + double("StatusStruct", current_state: "stopped"), + double("StatusStruct", current_state: "running") + ) end - it "calls the start command if one is specified" do - new_resource.start_command "sc start chef" - expect(provider).to receive(:shell_out!).with("#{new_resource.start_command}").and_return("Starting custom service") - provider.start_service - expect(new_resource.updated_by_last_action?).to be_truthy + context "run_as_user user is specified" do + let(:run_as_user) { provider.new_resource.class.properties[:run_as_user].default } + + before do + provider.new_resource.run_as_user run_as_user + end + + it "configures service run_as_user and run_as_password" do + expect(provider).to receive(:configure_service_run_as_properties).and_call_original + expect(Win32::Service).to receive(:configure) + provider.start_service + end end - it "uses the built-in command if no start command is specified" do - expect(Win32::Service).to receive(:start).with(new_resource.service_name) - provider.start_service - expect(new_resource.updated_by_last_action?).to be_truthy + context "run_as_user user is not specified" do + before do + expect(provider.new_resource.property_is_set?(:run_as_user)).to be false + end + + it "does not configure service run_as_user and run_as_password" do + expect(Win32::Service).not_to receive(:configure) + provider.start_service + end + end + + context "start_command is specified" do + let(:start_command) { "sc start #{chef_service_name}" } + + before do + new_resource.start_command start_command + allow(provider).to receive(:shell_out!).with(start_command) + end + + it "shells out the start_command" do + expect(provider).to receive(:shell_out!).with(start_command) + provider.start_service + end + + it "does not call Win32::Service.start" do + expect(Win32::Service).not_to receive(:start) + provider.start_service + end + + it "is updated by last action" do + provider.start_service + expect(new_resource).to be_updated_by_last_action + end + end + + context "start_command is not specified" do + before do + expect(new_resource.start_command).to be_nil + end + + it "uses the built-in command" do + expect(Win32::Service).to receive(:start).with(new_resource.service_name) + provider.start_service + end + + it "does not shell out the start_command" do + expect(provider).not_to receive(:shell_out!) + provider.start_service + end + + it "is updated by last action" do + provider.start_service + expect(new_resource).to be_updated_by_last_action + end end it "does nothing if the service does not exist" do allow(Win32::Service).to receive(:exists?).with(new_resource.service_name).and_return(false) - expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) + expect(Win32::Service).not_to receive(:start) provider.start_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).not_to be_updated_by_last_action end it "does nothing if the service is running" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "running")) + double("StatusStruct", current_state: "running") + ) provider.load_current_resource expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) provider.start_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).not_to be_updated_by_last_action end - it "raises an error if the service is paused" do - allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "paused")) - provider.load_current_resource - expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) - expect { provider.start_service }.to raise_error( Chef::Exceptions::Service ) - expect(new_resource.updated_by_last_action?).to be_falsey + context "service is paused" do + before do + allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( + double("StatusStruct", current_state: "paused") + ) + provider.load_current_resource + end + + it "raises error" do + expect { provider.start_service }.to raise_error(Chef::Exceptions::Service) + end + + it "does not start service" do + expect(Win32::Service).not_to receive(:start) + expect(provider).not_to receive(:shell_out!) + expect { provider.start_service }.to raise_error(Chef::Exceptions::Service) + end + + it "is not updated by last action" do + expect { provider.start_service }.to raise_error(Chef::Exceptions::Service) + expect(new_resource).not_to be_updated_by_last_action + end end - it "waits and continues if the service is in start_pending" do - allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "start pending"), - double("StatusStruct", :current_state => "start pending"), - double("StatusStruct", :current_state => "running")) - provider.load_current_resource - expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) - provider.start_service - expect(new_resource.updated_by_last_action?).to be_falsey + context "service is in start_pending" do + before do + allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( + double("StatusStruct", current_state: "start pending"), + double("StatusStruct", current_state: "start pending"), + double("StatusStruct", current_state: "running") + ) + provider.load_current_resource + end + + it "waits until service is running" do + expect(provider).to receive(:wait_for_state).with(Chef::Provider::Service::Windows::RUNNING) + provider.start_service + end + + it "does not start service" do + expect(Win32::Service).not_to receive(:start) + expect(provider).not_to receive(:shell_out!) + provider.start_service + end + + it "is not updated by last action" do + provider.start_service + expect(new_resource).not_to be_updated_by_last_action + end end - it "fails if the service is in stop_pending" do - allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "stop pending")) - provider.load_current_resource - expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) - expect { provider.start_service }.to raise_error( Chef::Exceptions::Service ) - expect(new_resource.updated_by_last_action?).to be_falsey + context "service is in stop_pending" do + before do + allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( + double("StatusStruct", current_state: "stop pending") + ) + provider.load_current_resource + end + + it "raises error" do + expect { provider.start_service }.to raise_error(Chef::Exceptions::Service) + end + + it "does not start service" do + expect(Win32::Service).not_to receive(:start) + expect(provider).not_to receive(:shell_out!) + expect { provider.start_service }.to raise_error(Chef::Exceptions::Service) + end + + it "is not updated by last action" do + expect { provider.start_service }.to raise_error(Chef::Exceptions::Service) + expect(new_resource).not_to be_updated_by_last_action + end end describe "running as a different account" do - let(:old_run_as_user) { new_resource.run_as_user } - let(:old_run_as_password) { new_resource.run_as_password } - before do new_resource.run_as_user(".\\wallace") new_resource.run_as_password("Wensleydale") end - after do - new_resource.run_as_user(old_run_as_user) - new_resource.run_as_password(old_run_as_password) - end - - it "calls #grant_service_logon if the :run_as_user and :run_as_password attributes are present" do - expect(Win32::Service).to receive(:start) + it "calls #grant_service_logon if the :run_as_user and :run_as_password properties are present" do expect(provider).to receive(:grant_service_logon).and_return(true) provider.start_service end it "does not grant user SeServiceLogonRight if it already has it" do - expect(Win32::Service).to receive(:start) expect(Chef::ReservedNames::Win32::Security).to receive(:get_account_right).with("wallace").and_return([service_right]) expect(Chef::ReservedNames::Win32::Security).not_to receive(:add_account_right).with("wallace", service_right) provider.start_service end + + it "skips the rights check for LocalSystem" do + new_resource.run_as_user("LocalSystem") + expect(Chef::ReservedNames::Win32::Security).not_to receive(:get_account_right) + expect(Chef::ReservedNames::Win32::Security).not_to receive(:add_account_right) + provider.start_service + end end end @@ -180,77 +684,83 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do before(:each) do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "running"), - double("StatusStruct", :current_state => "stopped")) + double("StatusStruct", current_state: "running"), + double("StatusStruct", current_state: "stopped") + ) end it "calls the stop command if one is specified" do - new_resource.stop_command "sc stop chef" - expect(provider).to receive(:shell_out!).with("#{new_resource.stop_command}").and_return("Stopping custom service") + new_resource.stop_command "sc stop #{chef_service_name}" + expect(provider).to receive(:shell_out!).with((new_resource.stop_command).to_s).and_return("Stopping custom service") provider.stop_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "uses the built-in command if no stop command is specified" do expect(Win32::Service).to receive(:stop).with(new_resource.service_name) provider.stop_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "does nothing if the service does not exist" do allow(Win32::Service).to receive(:exists?).with(new_resource.service_name).and_return(false) expect(Win32::Service).not_to receive(:stop).with(new_resource.service_name) provider.stop_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end it "does nothing if the service is stopped" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "stopped")) + double("StatusStruct", current_state: "stopped") + ) provider.load_current_resource expect(Win32::Service).not_to receive(:stop).with(new_resource.service_name) provider.stop_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end it "raises an error if the service is paused" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "paused")) + double("StatusStruct", current_state: "paused") + ) provider.load_current_resource expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) expect { provider.stop_service }.to raise_error( Chef::Exceptions::Service ) - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end it "waits and continue if the service is in stop_pending" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "stop pending"), - double("StatusStruct", :current_state => "stop pending"), - double("StatusStruct", :current_state => "stopped")) + double("StatusStruct", current_state: "stop pending"), + double("StatusStruct", current_state: "stop pending"), + double("StatusStruct", current_state: "stopped") + ) provider.load_current_resource expect(Win32::Service).not_to receive(:stop).with(new_resource.service_name) provider.stop_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end it "fails if the service is in start_pending" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "start pending")) + double("StatusStruct", current_state: "start pending") + ) provider.load_current_resource expect(Win32::Service).not_to receive(:stop).with(new_resource.service_name) expect { provider.stop_service }.to raise_error( Chef::Exceptions::Service ) - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end it "passes custom timeout to the stop command if provided" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "running")) + double("StatusStruct", current_state: "running") + ) new_resource.timeout 1 expect(Win32::Service).to receive(:stop).with(new_resource.service_name) Timeout.timeout(2) do expect { provider.stop_service }.to raise_error(Timeout::Error) end - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end end @@ -259,31 +769,33 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do it "calls the restart command if one is specified" do new_resource.restart_command "sc restart" - expect(provider).to receive(:shell_out!).with("#{new_resource.restart_command}") + expect(provider).to receive(:shell_out!).with((new_resource.restart_command).to_s) provider.restart_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "stops then starts the service if it is running" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "running"), - double("StatusStruct", :current_state => "stopped"), - double("StatusStruct", :current_state => "stopped"), - double("StatusStruct", :current_state => "running")) + double("StatusStruct", current_state: "running"), + double("StatusStruct", current_state: "stopped"), + double("StatusStruct", current_state: "stopped"), + double("StatusStruct", current_state: "running") + ) expect(Win32::Service).to receive(:stop).with(new_resource.service_name) expect(Win32::Service).to receive(:start).with(new_resource.service_name) provider.restart_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "just starts the service if it is stopped" do allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return( - double("StatusStruct", :current_state => "stopped"), - double("StatusStruct", :current_state => "stopped"), - double("StatusStruct", :current_state => "running")) + double("StatusStruct", current_state: "stopped"), + double("StatusStruct", current_state: "stopped"), + double("StatusStruct", current_state: "running") + ) expect(Win32::Service).to receive(:start).with(new_resource.service_name) provider.restart_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "does nothing if the service does not exist" do @@ -291,7 +803,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do expect(Win32::Service).not_to receive(:stop).with(new_resource.service_name) expect(Win32::Service).not_to receive(:start).with(new_resource.service_name) provider.restart_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end end @@ -299,34 +811,37 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do describe Chef::Provider::Service::Windows, "enable_service" do before(:each) do allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "disabled")) + double("ConfigStruct", start_type: "disabled") + ) end it "enables service" do - expect(Win32::Service).to receive(:configure).with(:service_name => new_resource.service_name, :start_type => Win32::Service::AUTO_START) + expect(Win32::Service).to receive(:configure).with(service_name: new_resource.service_name, start_type: Win32::Service::AUTO_START) provider.enable_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "does nothing if the service does not exist" do allow(Win32::Service).to receive(:exists?).with(new_resource.service_name).and_return(false) expect(Win32::Service).not_to receive(:configure) provider.enable_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end end describe Chef::Provider::Service::Windows, "action_enable" do it "does nothing if the service is enabled" do allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "auto start")) + double("ConfigStruct", start_type: "auto start") + ) expect(provider).not_to receive(:enable_service) provider.action_enable end it "enables the service if it is not set to automatic start" do allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "disabled")) + double("ConfigStruct", start_type: "disabled") + ) expect(provider).to receive(:enable_service) provider.action_enable end @@ -335,14 +850,16 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do describe Chef::Provider::Service::Windows, "action_disable" do it "does nothing if the service is disabled" do allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "disabled")) + double("ConfigStruct", start_type: "disabled") + ) expect(provider).not_to receive(:disable_service) provider.action_disable end it "disables the service if it is not set to disabled" do allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "auto start")) + double("ConfigStruct", start_type: "auto start") + ) expect(provider).to receive(:disable_service) provider.action_disable end @@ -351,54 +868,60 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do describe Chef::Provider::Service::Windows, "disable_service" do before(:each) do allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return( - double("ConfigStruct", :start_type => "auto start")) + double("ConfigStruct", start_type: "auto start") + ) end it "disables service" do expect(Win32::Service).to receive(:configure) provider.disable_service - expect(new_resource.updated_by_last_action?).to be_truthy + expect(new_resource).to be_updated_by_last_action end it "does nothing if the service does not exist" do allow(Win32::Service).to receive(:exists?).with(new_resource.service_name).and_return(false) expect(Win32::Service).not_to receive(:configure) provider.disable_service - expect(new_resource.updated_by_last_action?).to be_falsey + expect(new_resource).to_not be_updated_by_last_action end end describe Chef::Provider::Service::Windows, "action_configure_startup" do - { :automatic => "auto start", :manual => "demand start", :disabled => "disabled" }.each do |type, win32| + %i{automatic manual disabled}.each do |type| it "sets the startup type to #{type} if it is something else" do new_resource.startup_type(type) - allow(provider).to receive(:current_start_type).and_return("fire") + allow(provider).to receive(:current_startup_type).and_return(:fire) expect(provider).to receive(:set_startup_type).with(type) provider.action_configure_startup end it "leaves the startup type as #{type} if it is already set" do new_resource.startup_type(type) - allow(provider).to receive(:current_start_type).and_return(win32) + allow(provider).to receive(:current_startup_type).and_return(type) expect(provider).not_to receive(:set_startup_type).with(type) provider.action_configure_startup end end + + it "calls converge_delayed_start" do + expect(provider).to receive(:converge_delayed_start) + provider.action_configure_startup + end end describe Chef::Provider::Service::Windows, "set_start_type" do it "when called with :automatic it calls Win32::Service#configure with Win32::Service::AUTO_START" do - expect(Win32::Service).to receive(:configure).with(:service_name => new_resource.service_name, :start_type => Win32::Service::AUTO_START) + expect(Win32::Service).to receive(:configure).with(service_name: new_resource.service_name, start_type: Win32::Service::AUTO_START) provider.send(:set_startup_type, :automatic) end it "when called with :manual it calls Win32::Service#configure with Win32::Service::DEMAND_START" do - expect(Win32::Service).to receive(:configure).with(:service_name => new_resource.service_name, :start_type => Win32::Service::DEMAND_START) + expect(Win32::Service).to receive(:configure).with(service_name: new_resource.service_name, start_type: Win32::Service::DEMAND_START) provider.send(:set_startup_type, :manual) end it "when called with :disabled it calls Win32::Service#configure with Win32::Service::DISABLED" do - expect(Win32::Service).to receive(:configure).with(:service_name => new_resource.service_name, :start_type => Win32::Service::DISABLED) + expect(Win32::Service).to receive(:configure).with(service_name: new_resource.service_name, start_type: Win32::Service::DISABLED) provider.send(:set_startup_type, :disabled) end |