diff options
-rw-r--r-- | lib/puppet/provider/package/appdmg.rb | 3 | ||||
-rw-r--r-- | lib/puppet/provider/service/launchd.rb | 42 | ||||
-rwxr-xr-x | spec/unit/provider/service/launchd.rb | 134 |
3 files changed, 158 insertions, 21 deletions
diff --git a/lib/puppet/provider/package/appdmg.rb b/lib/puppet/provider/package/appdmg.rb index 2ee82a95d..ee8726cbc 100644 --- a/lib/puppet/provider/package/appdmg.rb +++ b/lib/puppet/provider/package/appdmg.rb @@ -12,9 +12,6 @@ # As a result, we store installed .app.dmg file names # in /var/db/.puppet_appdmg_installed_<name> -# require 'ruby-debug' -# Debugger.start - require 'puppet/provider/package' Puppet::Type.type(:package).provide(:appdmg, :parent => Puppet::Provider::Package) do desc "Package management which copies application bundles to a target." diff --git a/lib/puppet/provider/service/launchd.rb b/lib/puppet/provider/service/launchd.rb index e51451cac..11d7bd2b4 100644 --- a/lib/puppet/provider/service/launchd.rb +++ b/lib/puppet/provider/service/launchd.rb @@ -89,8 +89,8 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do # finds the path for a given label and returns the path and parsed plist # as an array of [path, plist]. Note plist is really a Hash here. - def self.plist_from_label(label) - job = self.jobsearch(label) + def plist_from_label(label) + job = self.class.jobsearch(label) job_path = job[label] job_plist = Plist::parse_xml(job_path) if not job_plist @@ -103,10 +103,8 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do def status # launchctl list <jobname> exits zero if the job is loaded # and non-zero if it isn't. Simple way to check... - cmds = [] - cmds << :launchctl << "list" << @resource[:name] begin - execute(cmds) + launchctl :list, resource[:name] return :running rescue Puppet::ExecutionFailure return :stopped @@ -118,11 +116,10 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do # conditionally enable at load, then disable by modifying the plist file # directly. def start - job = self.class.jobsearch(@resource[:name]) - job_path = job[@resource[:name]] + job_path, job_plist = plist_from_label(resource[:name]) did_enable_job = false cmds = [] - cmds << :launchctl << "load" + cmds << :launchctl << :load if self.enabled? == :false # launchctl won't load disabled jobs cmds << "-w" did_enable_job = true @@ -131,24 +128,33 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do begin execute(cmds) rescue Puppet::ExecutionFailure - raise Puppet::Error.new("Unable to start service: %s at path: %s" % [@resource[:name], job_path]) + raise Puppet::Error.new("Unable to start service: %s at path: %s" % [resource[:name], job_path]) end # As load -w clears the Disabled flag, we need to add it in after - if did_enable_job and @resource[:enable] == :false + if did_enable_job and resource[:enable] == :false self.disable end end def stop - job = self.class.jobsearch(@resource[:name]) - job_path = job[@resource[:name]] + job_path, job_plist = plist_from_label(resource[:name]) + did_disable_job = false cmds = [] - cmds << :launchctl << "unload" << job_path + cmds << :launchctl << :unload + if self.enabled? == :true # keepalive jobs can't be stopped without disabling + cmds << "-w" + did_disable_job = true + end + cmds << job_path begin execute(cmds) rescue Puppet::ExecutionFailure - raise Puppet::Error.new("Unable to stop service: %s at path: %s" % [@resource[:name], job_path]) + raise Puppet::Error.new("Unable to stop service: %s at path: %s" % [resource[:name], job_path]) + end + # As unload -w sets the Disabled flag, we need to add it in after + if did_disable_job and resource[:enable] == :true + self.enable end end @@ -156,7 +162,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do # launchd jobs are enabled by default. They are only disabled if the key # "Disabled" is set to true, but it can also be set to false to enable it. def enabled? - job_path, job_plist = self.class.plist_from_label(@resource[:name]) + job_path, job_plist = plist_from_label(resource[:name]) if job_plist.has_key?("Disabled") if job_plist["Disabled"] # inverse of disabled is enabled return :false @@ -170,8 +176,8 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do # rather than dealing with launchctl as it is unable to change the Disabled flag # without actually loading/unloading the job. def enable - job_path, job_plist = self.class.plist_from_label(@resource[:name]) - if not self.enabled? + job_path, job_plist = plist_from_label(resource[:name]) + if self.enabled? == :false job_plist.delete("Disabled") Plist::Emit.save_plist(job_plist, job_path) end @@ -179,7 +185,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do def disable - job_path, job_plist = self.class.plist_from_label(@resource[:name]) + job_path, job_plist = plist_from_label(resource[:name]) job_plist["Disabled"] = true Plist::Emit.save_plist(job_plist, job_path) end diff --git a/spec/unit/provider/service/launchd.rb b/spec/unit/provider/service/launchd.rb new file mode 100755 index 000000000..9650ea423 --- /dev/null +++ b/spec/unit/provider/service/launchd.rb @@ -0,0 +1,134 @@ +#!/usr/bin/env ruby +# +# Unit testing for the launchd service provider +# + +require File.dirname(__FILE__) + '/../../../spec_helper' + +require 'puppet' + +provider_class = Puppet::Type.type(:service).provider(:launchd) + +describe provider_class do + + before :each do + # Create a mock resource + @resource = stub 'resource' + + @provider = provider_class.new + @joblabel = "com.foo.food" + @jobplist = {} + + # A catch all; no parameters set + @resource.stubs(:[]).returns(nil) + + # But set name, ensure and enable + @resource.stubs(:[]).with(:name).returns @joblabel + @resource.stubs(:[]).with(:ensure).returns :enabled + @resource.stubs(:[]).with(:enable).returns :true + @resource.stubs(:ref).returns "Service[#{@joblabel}]" + + # stub out the provider methods that actually touch the filesystem + # or execute commands + @provider.stubs(:plist_from_label).returns([@joblabel, @jobplist]) + @provider.stubs(:execute).returns("") + @provider.stubs(:resource).returns @resource + end + + it "should have a start method for #{@provider.object_id}" do + @provider.should respond_to(:start) + end + + it "should have a stop method" do + @provider.should respond_to(:stop) + 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 + + it "should have a status method" do + @provider.should respond_to(:status) + end + + + describe "when checking status" do + it "should call the external command 'launchctl list' once" do + @provider.expects("launchctl").with(:list, @resource[:name]).returns(:running).once + @provider.status + end + end + + describe "when starting the service" do + it "should look for the relevant plist once" do + @provider.expects(:plist_from_label).once + @provider.start + end + it "should execute 'launchctl load' once without writing to the plist if the job is enabled" do + @provider.stubs(:enabled?).returns :true + @provider.expects(:execute).with([:launchctl, :load, @resource[:name]]).once + @provider.start + end + it "should execute 'launchctl load' with writing to the plist once if the job is disabled" do + @provider.stubs(:enabled?).returns :false + @provider.expects(:execute).with([:launchctl, :load, "-w", @resource[:name]]).once + @provider.start + end + it "should disable the job once if the job is disabled and should be disabled at boot" do + @provider.stubs(:enabled?).returns :false + @resource.stubs(:[]).with(:enable).returns :false + @provider.expects(:disable).once + @provider.start + end + end + + describe "when stopping the service" do + it "should look for the relevant plist once" do + @provider.expects(:plist_from_label).once + @provider.stop + end + it "should execute 'launchctl unload' once without writing to the plist if the job is disabled" do + @provider.stubs(:enabled?).returns :false + @provider.expects(:execute).with([:launchctl, :unload, @resource[:name]]).once + @provider.stop + end + it "should execute 'launchctl unload' with writing to the plist once if the job is enabled" do + @provider.stubs(:enabled?).returns :true + @provider.expects(:execute).with([:launchctl, :unload, "-w", @resource[:name]]).once + @provider.stop + end + it "should enable the job once if the job is enabled and should be enabled at boot" do + @provider.stubs(:enabled?).returns :true + @resource.stubs(:[]).with(:enable).returns :true + @provider.expects(:enable).once + @provider.stop + end + end + + describe "when enabling the service" do + it "should look for the relevant plist once" do + @provider.expects(:plist_from_label).once + @provider.stop + end + it "should check if the job is enabled once" do + @provider.expects(:enabled?).once + @provider.stop + end + end + + describe "when disabling the service" do + it "should look for the relevant plist once" do + @provider.expects(:plist_from_label).once + @provider.stop + end + end + + end |