diff --git a/lib/puppet/provider/service/windows.rb b/lib/puppet/provider/service/windows.rb index 56d56b0a9..d77f3b44a 100644 --- a/lib/puppet/provider/service/windows.rb +++ b/lib/puppet/provider/service/windows.rb @@ -1,97 +1,97 @@ # Windows Service Control Manager (SCM) provider require 'win32/service' if Puppet.features.microsoft_windows? Puppet::Type.type(:service).provide :windows do desc "Support for Windows Service Control Manager (SCM). Services are controlled according to win32-service gem. * All SCM operations (start/stop/enable/disable/query) are supported. * Control of service groups (dependencies) is not yet supported." defaultfor :operatingsystem => :windows confine :operatingsystem => :windows has_feature :refreshable def enable w32ss = Win32::Service.configure( 'service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_AUTO_START ) raise Puppet::Error.new("Win32 service enable of #{@resource[:name]} failed" ) if( w32ss.nil? ) rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot enable #{@resource[:name]}, error was: #{detail}" ) end def disable w32ss = Win32::Service.configure( 'service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DISABLED ) raise Puppet::Error.new("Win32 service disable of #{@resource[:name]} failed" ) if( w32ss.nil? ) rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot disable #{@resource[:name]}, error was: #{detail}" ) end def manual_start w32ss = Win32::Service.configure( 'service_name' => @resource[:name], 'start_type' => Win32::Service::SERVICE_DEMAND_START ) raise Puppet::Error.new("Win32 service manual enable of #{@resource[:name]} failed" ) if( w32ss.nil? ) rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot enable #{@resource[:name]} for manual start, error was: #{detail}" ) end def enabled? w32ss = Win32::Service.config_info( @resource[:name] ) raise Puppet::Error.new("Win32 service query of #{@resource[:name]} failed" ) unless( !w32ss.nil? && w32ss.instance_of?( Struct::ServiceConfigInfo ) ) debug("Service #{@resource[:name]} start type is #{w32ss.start_type}") case w32ss.start_type when Win32::Service.get_start_type(Win32::Service::SERVICE_AUTO_START), Win32::Service.get_start_type(Win32::Service::SERVICE_BOOT_START), Win32::Service.get_start_type(Win32::Service::SERVICE_SYSTEM_START) - true + :true when Win32::Service.get_start_type(Win32::Service::SERVICE_DEMAND_START) :manual when Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) - false + :false else raise Puppet::Error.new("Unknown start type: #{w32ss.start_type}") end rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot get start type for #{@resource[:name]}, error was: #{detail}" ) end def start Win32::Service.start( @resource[:name] ) rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot start #{@resource[:name]}, error was: #{detail}" ) end def stop Win32::Service.stop( @resource[:name] ) rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot start #{@resource[:name]}, error was: #{detail}" ) end def restart self.stop self.start end def status w32ss = Win32::Service.status( @resource[:name] ) raise Puppet::Error.new("Win32 service query of #{@resource[:name]} failed" ) unless( !w32ss.nil? && w32ss.instance_of?( Struct::ServiceStatus ) ) state = case w32ss.current_state when "stopped", "pause pending", "stop pending", "paused" then :stopped when "running", "continue pending", "start pending" then :running else raise Puppet::Error.new("Unknown service state '#{w32ss.current_state}' for service '#{@resource[:name]}'") end debug("Service #{@resource[:name]} is #{w32ss.current_state}") return state rescue Win32::Service::Error => detail raise Puppet::Error.new("Cannot get status of #{@resource[:name]}, error was: #{detail}" ) end # returns all providers for all existing services and startup state def self.instances Win32::Service.services.collect { |s| new(:name => s.service_name) } end end diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb index be2f33c20..fff875032 100755 --- a/spec/unit/provider/service/windows_spec.rb +++ b/spec/unit/provider/service/windows_spec.rb @@ -1,130 +1,130 @@ #!/usr/bin/env rspec # # Unit testing for the Windows service Provider # require 'spec_helper' require 'ostruct' require 'win32/service' if Puppet.features.microsoft_windows? provider_class = Puppet::Type.type(:service).provider(:windows) describe provider_class, :if => Puppet.features.microsoft_windows? do before :each do @provider = Puppet::Type.type(:service).provider(:windows) Puppet::Type.type(:service).stubs(:provider).returns(@provider) end describe ".instances" do it "should enumerate all services" do list_of_services = ['snmptrap', 'svchost', 'sshd'].map {|s| OpenStruct.new(:service_name => s)} Win32::Service.expects(:services).returns(list_of_services) provider_class.instances.map {|provider| provider.name}.should =~ ['snmptrap', 'svchost', 'sshd'] end end describe "#start" do it "should call out to the Win32::Service API to start the service" do Win32::Service.expects(:start).with('snmptrap') resource = Puppet::Type.type(:service).new(:name => 'snmptrap') resource.provider.start end it "should handle when Win32::Service.start raises a Win32::Service::Error" do Win32::Service.expects(:start).with('snmptrap').raises( Win32::Service::Error.new("The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.") ) resource = Puppet::Type.type(:service).new(:name => 'snmptrap') expect { resource.provider.start }.to raise_error( Puppet::Error, /Cannot start snmptrap, error was: The service cannot be started, either/ ) end end describe "#stop" do it "should stop a running service" it "should not try to stop an already stopped service" end describe "#status" do ['stopped', 'paused', 'stop pending', 'pause pending'].each do |state| it "should report a #{state} service as stopped" do Win32::Service.expects(:status).with('snmptrap').returns( stub( 'struct_service_status', :instance_of? => Struct::ServiceStatus, :current_state => state ) ) resource = Puppet::Type.type(:service).new(:name => 'snmptrap') resource.provider.status.should == :stopped end end ["running", "continue pending", "start pending" ].each do |state| it "should report a #{state} service as running" do Win32::Service.expects(:status).with('snmptrap').returns( stub( 'struct_service_status', :instance_of? => Struct::ServiceStatus, :current_state => state ) ) resource = Puppet::Type.type(:service).new(:name => 'snmptrap') resource.provider.status.should == :running end end end describe "#enabled?" do it "should report a service with a startup type of manual as manual" do Win32::Service.expects(:config_info).with('snmptrap').returns( stub( 'struct_config_info', :instance_of? => Struct::ServiceConfigInfo, :start_type => Win32::Service.get_start_type(Win32::Service::SERVICE_DEMAND_START) ) ) resource = Puppet::Type.type(:service).new(:name => 'snmptrap') resource.provider.enabled?.should == :manual end it "should report a service with a startup type of disabled as false" do Win32::Service.expects(:config_info).with('snmptrap').returns( stub( 'struct_config_info', :instance_of? => Struct::ServiceConfigInfo, :start_type => Win32::Service.get_start_type(Win32::Service::SERVICE_DISABLED) ) ) resource = Puppet::Type.type(:service).new(:name => 'snmptrap') - resource.provider.enabled?.should == false + resource.provider.enabled?.should == :false end # We need to guard this section explicitly since rspec will always # construct all examples, even if it isn't going to run them. if Puppet.features.microsoft_windows? [Win32::Service::SERVICE_AUTO_START, Win32::Service::SERVICE_BOOT_START, Win32::Service::SERVICE_SYSTEM_START].each do |start_type_const| start_type = Win32::Service.get_start_type(start_type_const) it "should report a service with a startup type of '#{start_type}' as true" do Win32::Service.expects(:config_info).with('snmptrap').returns( stub( 'struct_config_info', :instance_of? => Struct::ServiceConfigInfo, :start_type => start_type ) ) resource = Puppet::Type.type(:service).new(:name => 'snmptrap') - resource.provider.enabled?.should == true + resource.provider.enabled?.should == :true end end end end end