summaryrefslogtreecommitdiff
path: root/lib/chef/provider/service/macosx.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/provider/service/macosx.rb')
-rw-r--r--lib/chef/provider/service/macosx.rb82
1 files changed, 68 insertions, 14 deletions
diff --git a/lib/chef/provider/service/macosx.rb b/lib/chef/provider/service/macosx.rb
index 4f2de2ccbf..ca78c2eaee 100644
--- a/lib/chef/provider/service/macosx.rb
+++ b/lib/chef/provider/service/macosx.rb
@@ -17,6 +17,7 @@
#
require 'chef/provider/service'
+require 'rexml/document'
class Chef
class Provider
@@ -41,6 +42,7 @@ class Chef
@current_resource.service_name(@new_resource.service_name)
@plist_size = 0
@plist = find_service_plist
+ @service_label = find_service_label
set_service_status
@current_resource
@@ -48,14 +50,6 @@ class Chef
def define_resource_requirements
#super
- requirements.assert(:enable) do |a|
- a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :enable"
- end
-
- requirements.assert(:disable) do |a|
- a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :disable"
- end
-
requirements.assert(:reload) do |a|
a.failure_message Chef::Exceptions::UnsupportedAction, "#{self.to_s} does not support :reload"
end
@@ -66,6 +60,12 @@ class Chef
end
requirements.assert(:all_actions) do |a|
+ a.assertion { !@service_label.to_s.empty? }
+ a.failure_message Chef::Exceptions::Service,
+ "Could not find service's label in plist file '#{@plist}'!"
+ end
+
+ requirements.assert(:all_actions) do |a|
a.assertion { @plist_size > 0 }
# No failrue here in original code - so we also will not
# fail. Instead warn that the service is potentially missing
@@ -74,7 +74,6 @@ class Chef
@current_resource.running(false)
end
end
-
end
def start_service
@@ -111,19 +110,56 @@ class Chef
end
end
+ # On OS/X, enabling a service has the side-effect of starting it,
+ # and disabling a service has the side-effect of stopping it.
+ #
+ # This makes some sense on OS/X since launchctl is an "init"-style
+ # supervisor that will restart daemons that are crashing, etc.
+ def enable_service
+ if @current_resource.enabled
+ Chef::Log.debug("#{@new_resource} already enabled, not enabling")
+ else
+ shell_out!(
+ "launchctl load -w '#{@plist}'",
+ :user => @owner_uid, :group => @owner_gid
+ )
+ end
+ end
+
+ def disable_service
+ unless @current_resource.enabled
+ Chef::Log.debug("#{@new_resource} not enabled, not disabling")
+ else
+ shell_out!(
+ "launchctl unload -w '#{@plist}'",
+ :user => @owner_uid, :group => @owner_gid
+ )
+ end
+ end
def set_service_status
- return if @plist == nil
+ return if @plist == nil or @service_label.to_s.empty?
- @current_resource.enabled(!@plist.nil?)
+ cmd = shell_out(
+ "launchctl list #{@service_label}",
+ :user => @owner_uid, :group => @owner_gid
+ )
+
+ if cmd.exitstatus == 0
+ @current_resource.enabled(true)
+ else
+ @current_resource.enabled(false)
+ end
if @current_resource.enabled
@owner_uid = ::File.stat(@plist).uid
@owner_gid = ::File.stat(@plist).gid
- shell_out!("launchctl list", :user => @owner_uid, :group => @owner_gid).stdout.each_line do |line|
+ shell_out!(
+ "launchctl list", :user => @owner_uid, :group => @owner_gid
+ ).stdout.each_line do |line|
case line
- when /(\d+|-)\s+(?:\d+|-)\s+(.*\.?)#{@current_resource.service_name}/
+ when /(\d+|-)\s+(?:\d+|-)\s+(.*\.?)#{@service_label}/
pid = $1
@current_resource.running(!pid.to_i.zero?)
end
@@ -135,9 +171,27 @@ class Chef
private
+ def find_service_label
+ # Most services have the same internal label as the name of the
+ # plist file. However, there is no rule saying that *has* to be
+ # the case, and some core services (notably, ssh) do not follow
+ # this rule.
+
+ # plist files can come in XML or Binary formats. this command
+ # will make sure we get XML every time.
+ plist_xml = shell_out!("plutil -convert xml1 -o - #{@plist}").stdout
+
+ plist_doc = REXML::Document.new(plist_xml)
+ plist_doc.elements[
+ "/plist/dict/key[text()='Label']/following::string[1]/text()"]
+ end
+
def find_service_plist
plists = PLIST_DIRS.inject([]) do |results, dir|
- entries = Dir.glob("#{::File.expand_path(dir)}/*#{@current_resource.service_name}*.plist")
+ edir = ::File.expand_path(dir)
+ entries = Dir.glob(
+ "#{edir}/*#{@current_resource.service_name}*.plist"
+ )
entries.any? ? results << entries : results
end
plists.flatten!