diff --git a/lib/puppet/provider/service/redhat.rb b/lib/puppet/provider/service/redhat.rb index ddcbe0e8c..27bdbb820 100755 --- a/lib/puppet/provider/service/redhat.rb +++ b/lib/puppet/provider/service/redhat.rb @@ -1,82 +1,82 @@ # Manage Red Hat services. Start/stop uses /sbin/service and enable/disable uses chkconfig Puppet::Type.type(:service).provide :redhat, :parent => :init, :source => :init do desc "Red Hat's (and probably many others) form of ``init``-style service management: Uses ``chkconfig`` for service enabling and disabling. " commands :chkconfig => "/sbin/chkconfig", :service => "/sbin/service" defaultfor :operatingsystem => [:redhat, :fedora, :suse, :centos, :sles, :oel, :ovm] def self.instances # this exclude list is all from /sbin/service (5.x), but I did not exclude kudzu - self.get_services(['/etc/init.d/'], ['functions', 'halt', 'killall', 'single', 'linuxconf']) + self.get_services(['/etc/init.d'], ['functions', 'halt', 'killall', 'single', 'linuxconf']) end def self.defpath superclass.defpath end # Remove the symlinks def disable begin output = chkconfig(@resource[:name], :off) rescue Puppet::ExecutionFailure raise Puppet::Error, "Could not disable %s: %s" % [self.name, output] end end def enabled? begin output = chkconfig(@resource[:name]) rescue Puppet::ExecutionFailure return :false end # If it's disabled on SuSE, then it will print output showing "off" # at the end if output =~ /.* off$/ return :false end return :true end # Don't support them specifying runlevels; always use the runlevels # in the init scripts. def enable begin output = chkconfig(@resource[:name], :on) rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not enable %s: %s" % [self.name, detail] end end def initscript raise Puppet::Error, "Do not directly call the init script for '%s'; use 'service' instead" % @resource[:name] end # use hasstatus=>true when its set for the provider. def statuscmd ((@resource.provider.get(:hasstatus) == true) || (@resource[:hasstatus] == :true)) && [command(:service), @resource[:name], "status"] end def restartcmd (@resource[:hasrestart] == :true) && [command(:service), @resource[:name], "restart"] end def startcmd [command(:service), @resource[:name], "start"] end def stopcmd [command(:service), @resource[:name], "stop"] end end diff --git a/spec/unit/provider/service/init_spec.rb b/spec/unit/provider/service/init_spec.rb index 32bfaa204..6dd42f54c 100755 --- a/spec/unit/provider/service/init_spec.rb +++ b/spec/unit/provider/service/init_spec.rb @@ -1,121 +1,168 @@ #!/usr/bin/env ruby # # Unit testing for the Init service Provider # require File.dirname(__FILE__) + '/../../../spec_helper' provider_class = Puppet::Type.type(:service).provider(:init) describe provider_class do before :each do + @class = Puppet::Type.type(:service).provider(:init) @resource = stub 'resource' @resource.stubs(:[]).returns(nil) @resource.stubs(:[]).with(:name).returns "myservice" # @resource.stubs(:[]).with(:ensure).returns :enabled @resource.stubs(:[]).with(:path).returns ["/service/path","/alt/service/path"] # @resource.stubs(:ref).returns "Service[myservice]" File.stubs(:directory?).returns(true) @provider = provider_class.new @provider.resource = @resource end + describe "when getting all service instances" do + before :each do + @services = ['one', 'two', 'three', 'four'] + Dir.stubs(:entries).returns @services + FileTest.stubs(:directory?).returns(true) + FileTest.stubs(:executable?).returns(true) + @class.stubs(:defpath).returns('tmp') + end + it "should return instances for all services" do + @services.each do |inst| + @class.expects(:new).with{|hash| hash[:name] == inst}.returns("#{inst}_instance") + end + results = @services.collect {|x| "#{x}_instance"} + @class.instances.should == results + end + it "should omit an array of services from exclude list" do + exclude = ['two', 'four'] + (@services-exclude).each do |inst| + @class.expects(:new).with{|hash| hash[:name] == inst}.returns("#{inst}_instance") + end + results = (@services-exclude).collect {|x| "#{x}_instance"} + @class.get_services(@class.defpath, exclude).should == results + end + it "should omit a single service from the exclude list" do + exclude = 'two' + (@services-exclude.to_a).each do |inst| + @class.expects(:new).with{|hash| hash[:name] == inst}.returns("#{inst}_instance") + end + results = @services.reject{|x| x==exclude }.collect {|x| "#{x}_instance"} + @class.get_services(@class.defpath, exclude).should == results + end + it "should use defpath" do + @services.each do |inst| + @class.expects(:new).with{|hash| hash[:path] == @class.defpath}.returns("#{inst}_instance") + end + results = @services.sort.collect {|x| "#{x}_instance"} + @class.instances.sort.should == results + end + it "should set hasstatus to true for providers" do + @services.each do |inst| + @class.expects(:new).with{|hash| hash[:name] == inst && hash[:hasstatus] == true}.returns("#{inst}_instance") + end + results = @services.collect {|x| "#{x}_instance"} + @class.instances.should == results + end + end describe "when searching for the init script" do it "should discard paths that do not exist" do File.stubs(:exist?).returns(false) File.stubs(:directory?).returns(false) @provider.paths.should be_empty end it "should discard paths that are not directories" do File.stubs(:exist?).returns(true) File.stubs(:directory?).returns(false) @provider.paths.should be_empty end it "should be able to find the init script in the service path" do File.expects(:stat).with("/service/path/myservice").returns true @provider.initscript.should == "/service/path/myservice" end it "should be able to find the init script in the service path" do File.expects(:stat).with("/alt/service/path/myservice").returns true @provider.initscript.should == "/alt/service/path/myservice" end it "should fail if the service isn't there" do lambda { @provider.initscript }.should raise_error(Puppet::Error, "Could not find init script for 'myservice'") end end describe "if the init script is present" do before :each do File.stubs(:stat).with("/service/path/myservice").returns true end [:start, :stop, :status, :restart].each do |method| it "should have a #{method} method" do @provider.should respond_to(method) end describe "when running #{method}" do it "should use any provided explicit command" do @resource.stubs(:[]).with(method).returns "/user/specified/command" @provider.expects(:execute).with { |command, *args| command == ["/user/specified/command"] } @provider.send(method) end it "should pass #{method} to the init script when no explicit command is provided" do @resource.stubs(:[]).with("has#{method}".intern).returns :true @provider.expects(:execute).with { |command, *args| command == ["/service/path/myservice",method]} @provider.send(method) end end end describe "when checking status" do describe "when hasstatus is :true" do before :each do @resource.stubs(:[]).with(:hasstatus).returns :true end it "should execute the command" do @provider.expects(:texecute).with(:status, ['/service/path/myservice', :status], false).returns("") @provider.status end it "should consider the process running if the command returns 0" do @provider.expects(:texecute).with(:status, ['/service/path/myservice', :status], false).returns("") $?.stubs(:exitstatus).returns(0) @provider.status.should == :running end [-10,-1,1,10].each { |ec| it "should consider the process stopped if the command returns something non-0" do @provider.expects(:texecute).with(:status, ['/service/path/myservice', :status], false).returns("") $?.stubs(:exitstatus).returns(ec) @provider.status.should == :stopped end } end describe "when hasstatus is not :true" do it "should consider the service :running if it has a pid" do @provider.expects(:getpid).returns "1234" @provider.status.should == :running end it "should consider the service :stopped if it doesn't have a pid" do @provider.expects(:getpid).returns nil @provider.status.should == :stopped end end end describe "when restarting and hasrestart is not :true" do it "should stop and restart the process" do @provider.expects(:texecute).with(:stop, ['/service/path/myservice', :stop ], true).returns("") @provider.expects(:texecute).with(:start,['/service/path/myservice', :start], true).returns("") $?.stubs(:exitstatus).returns(0) @provider.restart end end end end diff --git a/spec/unit/provider/service/redhat_spec.rb b/spec/unit/provider/service/redhat_spec.rb index 47997dca3..591ef2d96 100755 --- a/spec/unit/provider/service/redhat_spec.rb +++ b/spec/unit/provider/service/redhat_spec.rb @@ -1,96 +1,121 @@ #!/usr/bin/env ruby # # Unit testing for the RedHat service Provider # - require File.dirname(__FILE__) + '/../../../spec_helper' provider_class = Puppet::Type.type(:service).provider(:redhat) describe provider_class do before :each do + @class = Puppet::Type.type(:service).provider(:redhat) @resource = stub 'resource' @resource.stubs(:[]).returns(nil) @resource.stubs(:[]).with(:name).returns "myservice" - @provider = provider_class.new + @resource.stubs(:provider).returns @provider @provider.resource = @resource + @provider.stubs(:get).with(:hasstatus).returns false FileTest.stubs(:file?).with('/sbin/service').returns true FileTest.stubs(:executable?).with('/sbin/service').returns true end + + # test self.instances + describe "when getting all service instances" do + before :each do + @services = ['one', 'two', 'three', 'four', 'kudzu', 'functions', 'halt', 'killall', 'single', 'linuxconf'] + @not_services = ['functions', 'halt', 'killall', 'single', 'linuxconf'] + Dir.stubs(:entries).returns @services + FileTest.stubs(:directory?).returns(true) + FileTest.stubs(:executable?).returns(true) + end + it "should return instances for all services" do + (@services-@not_services).each do |inst| + @class.expects(:new).with{|hash| hash[:name] == inst && hash[:path] == '/etc/init.d'}.returns("#{inst}_instance") + end + results = (@services-@not_services).collect {|x| "#{x}_instance"} + @class.instances.should == results + end + it "should call service status when initialized from provider" do + @resource.stubs(:[]).with(:status).returns nil + @provider.stubs(:get).with(:hasstatus).returns true + @provider.expects(:execute).with{|command, *args| command == ['/sbin/service', 'myservice', 'status']} + @provider.send(:status) + end + end it "should have an enabled? method" do @provider.should respond_to(:enabled?) end it "should have an enable method" do @provider.should respond_to(:enable) end it "should have a disable method" do @provider.should respond_to(:disable) end [:start, :stop, :status, :restart].each do |method| it "should have a #{method} method" do @provider.should respond_to(method) end describe "when running #{method}" do it "should use any provided explicit command" do @resource.stubs(:[]).with(method).returns "/user/specified/command" @provider.expects(:execute).with { |command, *args| command == ["/user/specified/command"] } @provider.send(method) end it "should execute the service script with #{method} when no explicit command is provided" do @resource.stubs(:[]).with("has#{method}".intern).returns :true @provider.expects(:execute).with { |command, *args| command == ['/sbin/service', 'myservice', method.to_s]} @provider.send(method) end end end describe "when checking status" do describe "when hasstatus is :true" do before :each do @resource.stubs(:[]).with(:hasstatus).returns :true end it "should execute the service script with fail_on_failure false" do @provider.expects(:texecute).with(:status, ['/sbin/service', 'myservice', 'status'], false) @provider.status end it "should consider the process running if the command returns 0" do @provider.expects(:texecute).with(:status, ['/sbin/service', 'myservice', 'status'], false) $?.stubs(:exitstatus).returns(0) @provider.status.should == :running end [-10,-1,1,10].each { |ec| it "should consider the process stopped if the command returns something non-0" do @provider.expects(:texecute).with(:status, ['/sbin/service', 'myservice', 'status'], false) $?.stubs(:exitstatus).returns(ec) @provider.status.should == :stopped end } end describe "when hasstatus is not :true" do it "should consider the service :running if it has a pid" do @provider.expects(:getpid).returns "1234" @provider.status.should == :running end it "should consider the service :stopped if it doesn't have a pid" do @provider.expects(:getpid).returns nil @provider.status.should == :stopped end end end describe "when restarting and hasrestart is not :true" do it "should stop and restart the process with the server script" do @provider.expects(:texecute).with(:stop, ['/sbin/service', 'myservice', 'stop'], true) @provider.expects(:texecute).with(:start, ['/sbin/service', 'myservice', 'start'], true) @provider.restart end end end