Skip to content

Instantly share code, notes, and snippets.

@raggi
Created April 17, 2011 07:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save raggi/923827 to your computer and use it in GitHub Desktop.
Save raggi/923827 to your computer and use it in GitHub Desktop.
A first stab at a launchd provider for chef
class Chef::Provider::Service::Launchd < Chef::Provider::Service::Simple
LAUNCHCTL_FORMAT = /([\d-]+)\s+([\d-]+)\s+([[:print:]]+)/
def initialize(new_resource, run_context)
raise ArgumentError, "run_context cannot be nil" unless run_context
super
run_context.node
end
def load_current_resource
@current_resource = Chef::Resource::Service.new(@new_resource.name)
@current_resource.service_name(@new_resource.service_name)
if @new_resource.status_command
Chef::Log.debug("#{@new_resource} you have specified a status command, running..")
begin
if run_command_with_systems_locale(:command => @new_resource.status_command) == 0
@current_resource.running true
end
rescue Chef::Exceptions::Exec
@current_resource.running false
nil
end
else
pid = launchctl_pid
if pid
@current_resource.enabled true
if pid > 0
@current_resource.running true
else
@current_resource.running false
end
else
@current_resource.enabled false
end
end
@current_resource
end
def start_service
if @current_resource.running
Chef::Log.debug("#{@new_resource}: Already running, not starting")
else
if @new_resource.start_command
super
else
file = launchctl_file
run_command_with_systems_locale(:command => "launchctl load #{file}")
run_command_with_systems_locale(:command => "launchctl start #{launchctl_name}")
end
end
end
def stop_service
unless @current_resource.running
Chef::Log.debug("#{@new_resource}: Not running, not stopping")
else
if @new_resource.stop_command
super
else
file = launchctl_file
run_command_with_systems_locale(:command => "launchctl unload #{file}")
end
end
end
def restart_service
if @new_resource.restart_command
super
else
run_command_with_systems_locale(:command => "launchctl stop #{launchctl_name}")
end
end
def reload_service
if @new_resource.reload_command
super
else
pid = launchctl_pid
run_command_with_systems_locale(:command => "kill -HUP #{pid}") if pid
end
end
def enable_service
# Macports integration:
run_command_with_systems_locale(:command => "port load #{@new_resource.service_name}") rescue nil
file = launchctl_file
run_command_with_systems_locale(:command => "launchctl load #{file}")
end
def disable_service
file = launchctl_file
run_command_with_systems_locale(:command => "launchctl unload #{file}")
# Macports integration:
run_command_with_systems_locale(:command => "port unload #{@new_resource.service_name}") rescue nil
end
# A pid or 0 if not running
def launchctl_pid
command = "launchctl list | grep #{@new_resource.service_name}"
status = popen4(command) do |pid, stdin, stdout, stderr|
stdout.each_line do |line|
line =~ LAUNCHCTL_FORMAT
pid, status, name = Regexp.last_match.captures
return pid.to_i if name =~ /#{Regexp.escape @new_resource.service_name}$/
end
end
nil
end
def launchctl_name
command = "launchctl list | grep #{@new_resource.service_name}"
status = popen4(command) do |pid, stdin, stdout, stderr|
stdout.each_line do |line|
line =~ LAUNCHCTL_FORMAT
pid, status, name = Regexp.last_match.captures
return name if name =~ /#{Regexp.escape @new_resource.service_name}$/
end
end
end
def launchctl_file
Dir["{~,/}Library/LaunchDaemons/*#{@new_resource.service_name}.plist"].first
end
end
@krobertson
Copy link

Was wondering if you intended to release this as a cookbook or had a license in mind for it.

I forked it here: https://gist.github.com/1060712/5ee1aa5b924069c2b0b4da8c912dc973a9dccac8

Mainly had to update launchctl_file to better support the home directory and to support LaunchDaemons as well as LaunchAgents files.

After that, it worked great!

@raggi
Copy link
Author

raggi commented Jul 3, 2011

I was thinking about submitting it as a patch, but haven't gotten around to it yet. It seems like it's a pain in the butt to test, I'm not really sure I want to mock out launchd.

@raggi
Copy link
Author

raggi commented Jul 3, 2011

License wise, feel free to take it as MIT.

Hmm. I copied some of this out of the Chef repo actually, so check that license too, if it's MIT that's fine, there's no conflict.

@krobertson
Copy link

I think chef is actually Apache.

Submitting it as a patch would be awesome, but yeah, not sure about testing. Have to look at how the others are tested. I got it working bu adding a "launchd" cookbook with a libraries directory and put it in there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment