diff --git a/lib/puppet/provider/service/openbsd.rb b/lib/puppet/provider/service/openbsd.rb index c84fc3d87..f91a3340e 100644 --- a/lib/puppet/provider/service/openbsd.rb +++ b/lib/puppet/provider/service/openbsd.rb @@ -1,93 +1,101 @@ Puppet::Type.type(:service).provide :openbsd, :parent => :init do desc "Provider for OpenBSD's rc.d daemon control scripts" commands :rcctl => '/usr/sbin/rcctl' confine :operatingsystem => :openbsd defaultfor :operatingsystem => :openbsd has_feature :flaggable def startcmd [command(:rcctl), '-f', :start, @resource[:name]] end def stopcmd [command(:rcctl), :stop, @resource[:name]] end def restartcmd (@resource[:hasrestart] == :true) && [command(:rcctl), '-f', :restart, @resource[:name]] end def statuscmd [command(:rcctl), :check, @resource[:name]] end # @api private # When storing the name, take into account not everything has # '_flags', like 'multicast_host' and 'pf'. def self.instances instances = [] begin execpipe([command(:rcctl), :status]) do |process| process.each_line do |line| match = /^(.*?)(?:_flags)?=(.*)$/.match(line) attributes_hash = { :name => match[1], :flags => match[2], :hasstatus => true, :provider => :openbsd, } instances << new(attributes_hash); end end instances rescue Puppet::ExecutionFailure return nil end end def enabled? output = execute([command(:rcctl), "status", @resource[:name]], :failonfail => false, :combine => false, :squelch => false).chomp if output == 'NO' self.debug("Is disabled") return :false else self.debug("Is enabled") return :true end end def enable self.debug("Enabling") if @resource[:flags] rcctl(:enable, @resource[:name], :flags, @resource[:flags]) else rcctl(:enable, @resource[:name]) end end def disable self.debug("Disabling") rcctl(:disable, @resource[:name]) end + def running? + output = execute([command(:rcctl), "check", @resource[:name]], + :failonfail => false, :combine => false, :squelch => false).chomp + return true if output.match(/\(ok\)/) + end + # Uses the wrapper to prevent failure when the service is not running; # rcctl(8) return non-zero in that case. def flags output = execute([command(:rcctl), "status", @resource[:name]], :failonfail => false, :combine => false, :squelch => false).chomp self.debug("Flags are: #{output}") output end def flags=(value) self.debug("Changing flags from #{flags} to #{value}") rcctl(:enable, @resource[:name], :flags, value) + # If the service is already running, force a restart as the flags have been changed. + rcctl(:restart, @resource[:name]) if running? end end diff --git a/spec/unit/provider/service/openbsd_spec.rb b/spec/unit/provider/service/openbsd_spec.rb index 676b9d9b3..777c348a7 100755 --- a/spec/unit/provider/service/openbsd_spec.rb +++ b/spec/unit/provider/service/openbsd_spec.rb @@ -1,178 +1,201 @@ #!/usr/bin/env ruby # # Unit testing for the OpenBSD service provider require 'spec_helper' provider_class = Puppet::Type.type(:service).provider(:openbsd) describe provider_class, :unless => Puppet.features.microsoft_windows? do before :each do Puppet::Type.type(:service).stubs(:defaultprovider).returns described_class Facter.stubs(:value).with(:operatingsystem).returns :openbsd FileTest.stubs(:file?).with('/usr/sbin/rcctl').returns true FileTest.stubs(:executable?).with('/usr/sbin/rcctl').returns true end describe "#instances" do it "should have an instances method" do described_class.should respond_to :instances end it "should list all available services" do described_class.stubs(:execpipe).with(['/usr/sbin/rcctl', :status]).yields File.read(my_fixture('rcctl_status')) described_class.instances.map(&:name).should == [ 'accounting', 'pf', 'postgresql', 'tftpd', 'wsmoused', 'xdm', ] end end describe "#start" do it "should use the supplied start command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :start => '/bin/foo')) provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true) provider.start end it "should start the service otherwise" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) provider.expects(:texecute).with(:start, ['/usr/sbin/rcctl', '-f', :start, 'sshd'], true) provider.start end end describe "#stop" do it "should use the supplied stop command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :stop => '/bin/foo')) provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true) provider.stop end it "should stop the service otherwise" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) provider.expects(:texecute).with(:stop, ['/usr/sbin/rcctl', :stop, 'sshd'], true) provider.stop end end describe "#status" do it "should use the status command from the resource" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) provider.expects(:execute).with(['/usr/sbin/rcctl', :status, 'sshd'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true).never provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => false, :combine => true) provider.status end it "should return :stopped when status command returns with a non-zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) provider.expects(:execute).with(['/usr/sbin/rcctl', :status, 'sshd'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true).never provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => false, :combine => true) $CHILD_STATUS.stubs(:exitstatus).returns 3 provider.status.should == :stopped end it "should return :running when status command returns with a zero exitcode" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :status => '/bin/foo')) provider.expects(:execute).with(['/usr/sbin/rcctl', :status, 'sshd'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true).never provider.expects(:execute).with(['/bin/foo'], :failonfail => false, :override_locale => false, :squelch => false, :combine => true) $CHILD_STATUS.stubs(:exitstatus).returns 0 provider.status.should == :running end end describe "#restart" do it "should use the supplied restart command if specified" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :restart => '/bin/foo')) provider.expects(:execute).with(['/usr/sbin/rcctl', '-f', :restart, 'sshd'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true).never provider.expects(:execute).with(['/bin/foo'], :failonfail => true, :override_locale => false, :squelch => false, :combine => true) provider.restart end it "should restart the service with rcctl restart if hasrestart is true" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => true)) provider.expects(:texecute).with(:restart, ['/usr/sbin/rcctl', '-f', :restart, 'sshd'], true) provider.restart end it "should restart the service with rcctl stop/start if hasrestart is false" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :hasrestart => false)) provider.expects(:texecute).with(:restart, ['/usr/sbin/rcctl', '-f', :restart, 'sshd'], true).never provider.expects(:texecute).with(:stop, ['/usr/sbin/rcctl', :stop, 'sshd'], true) provider.expects(:texecute).with(:start, ['/usr/sbin/rcctl', '-f', :start, 'sshd'], true) provider.restart end end describe "#enabled?" do it "should return :true if the service is enabled" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) described_class.stubs(:rcctl).with('status', 'sshd').returns('-6') provider.expects(:execute).with(['/usr/sbin/rcctl', 'status', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('-6') provider.enabled?.should == :true end it "should return :false if the service is disabled" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) described_class.stubs(:rcctl).with('status', 'sshd').returns('NO') provider.expects(:execute).with(['/usr/sbin/rcctl', 'status', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('NO') provider.enabled?.should == :false end end describe "#enable" do it "should run rcctl enable to enable the service" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) described_class.stubs(:rcctl).with(:enable, 'sshd').returns('') provider.expects(:rcctl).with(:enable, 'sshd') provider.enable end it "should run rcctl enable with flags if provided" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :flags => '-6')) described_class.stubs(:rcctl).with(:enable, 'sshd', :flags, '-6').returns('') provider.expects(:rcctl).with(:enable, 'sshd', :flags, '-6') provider.enable end end describe "#disable" do it "should run rcctl disable to disable the service" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) described_class.stubs(:rcctl).with(:disable, 'sshd').returns('') provider.expects(:rcctl).with(:disable, 'sshd') provider.disable end end + describe "#running?" do + it "should run rcctl check to check the service" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + described_class.stubs(:rcctl).with(:check, 'sshd').returns('sshd(ok)') + provider.expects(:execute).with(['/usr/sbin/rcctl', 'check', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('sshd(ok)') + provider.running?.should be_true + end + + it "should return true if the service is running" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + described_class.stubs(:rcctl).with(:check, 'sshd').returns('sshd(ok)') + provider.expects(:execute).with(['/usr/sbin/rcctl', 'check', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('sshd(ok)') + provider.running?.should be_true + end + + it "should return nil if the service is not running" do + provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) + described_class.stubs(:rcctl).with(:check, 'sshd').returns('sshd(failed)') + provider.expects(:execute).with(['/usr/sbin/rcctl', 'check', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('sshd(failed)') + provider.running?.should be_nil + end + end + describe "#flags" do it "should return flags when set" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd', :flags => '-6')) described_class.stubs(:rcctl).with(:status, 'sshd').returns('-6') provider.expects(:execute).with(['/usr/sbin/rcctl', 'status', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('-6') provider.flags end it "should return empty flags" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) described_class.stubs(:rcctl).with(:status, 'sshd').returns('') provider.expects(:execute).with(['/usr/sbin/rcctl', 'status', 'sshd'], :failonfail => false, :combine => false, :squelch => false).returns('') provider.flags end it "should return flags for special services" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'pf')) described_class.stubs(:rcctl).with(:status, 'pf').returns('YES') provider.expects(:execute).with(['/usr/sbin/rcctl', 'status', 'pf'], :failonfail => false, :combine => false, :squelch => false).returns('YES') provider.flags end end describe "#flags=" do it "should run rcctl to set flags" do provider = described_class.new(Puppet::Type.type(:service).new(:name => 'sshd')) described_class.stubs(:rcctl).with(:enable, 'sshd', :flags, '-4').returns('') provider.expects(:rcctl).with(:enable, 'sshd', :flags, '-4') provider.flags = '-4' end end end