summaryrefslogtreecommitdiffstats
path: root/spec/unit/provider/service
diff options
context:
space:
mode:
authorCameron Thomas <cameron@puppetlabs.com>2011-07-22 15:09:13 -0700
committerCameron Thomas <cameron@puppetlabs.com>2011-07-22 16:09:44 -0700
commit82476e8be41b62ce1767ab6854a72b481b917380 (patch)
tree55602239d5aff9e479e62cff0cc0e00078d06d00 /spec/unit/provider/service
parentca2f159caed691936bd9e87b59ccddc764066aa2 (diff)
downloadpuppet-82476e8be41b62ce1767ab6854a72b481b917380.tar.gz
puppet-82476e8be41b62ce1767ab6854a72b481b917380.tar.xz
puppet-82476e8be41b62ce1767ab6854a72b481b917380.zip
Add basic service provider for Windows
This provider allows us to query the system state through "puppet resource", and manage the ensure, and enabled properties of services on Windows. This also adds support for a new enabled value of 'manual' on Windows only. With this we support the three major start types for services on Windows, with the following mapping of enabled to start type: true => Automatic false => Disabled manual => Manual (Demand) We use the win32-service gem to provide access to the Windows APIs for our operations. This does add a new gem requirement for running Puppet on Windows, but we were already requiring some gems from the same suite that win32-service is a part of. When referring to a service, the simple service name must be used, instead of the display name. For example, "snmptrap", instead of "SNMP Trap". All system services are reported in 'puppet resource service', including those started prior to run level 3 (system, device drivers, etc.). These services should probably not be managed, without careful thought and planning. This currently does not support being able to move a service from {enabled => false, ensure => stopped} to {enabled => true, ensure => running} (or enabled => manual) in a single Puppet run, since Puppet currently always tries to sync ensure before any other property. Because of this, the puppet run will fail every time, and the service must first be managed as {ensure => stopped, enabled => true} (or enabled => manual), before it can be managed as running and automatic start or manual start. Reviewed by: Jacob Helwig <jacob@puppetlabs.com>
Diffstat (limited to 'spec/unit/provider/service')
-rwxr-xr-xspec/unit/provider/service/windows_spec.rb130
1 files changed, 130 insertions, 0 deletions
diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb
new file mode 100755
index 000000000..be2f33c20
--- /dev/null
+++ b/spec/unit/provider/service/windows_spec.rb
@@ -0,0 +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
+ 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
+ end
+ end
+ end
+ end
+end