From 66c4f6af84f33ac40ff2912a61ee9a3be2ca878c Mon Sep 17 00:00:00 2001 From: Mike Dodge Date: Tue, 27 Oct 2015 11:21:04 -0700 Subject: launchd --- lib/chef/provider/launchd.rb | 205 ++++++++++++++++++++++ lib/chef/providers.rb | 1 + lib/chef/resource/launchd.rb | 402 +++++++++++++++++++++++++++++++++++++++++++ lib/chef/resources.rb | 8 + 4 files changed, 616 insertions(+) create mode 100644 lib/chef/provider/launchd.rb create mode 100644 lib/chef/resource/launchd.rb (limited to 'lib/chef') diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb new file mode 100644 index 0000000000..a6f54e7627 --- /dev/null +++ b/lib/chef/provider/launchd.rb @@ -0,0 +1,205 @@ +# +# Author:: Mike Dodge () +# Copyright:: Copyright (c) 2015 Facebook, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/provider' +require 'chef/resource' +require 'chef/resource/file' +require 'chef/resource/cookbook_file' +require 'chef/resource/macosx_service' + +class Chef + class Provider + class Launchd < Chef::Provider + + def load_current_resource + @current_resource = Chef::Resource::Launchd.new(@new_resource.name) + @name = @new_resource.name + @label = @new_resource.label ? @new_resource.label : @name + @backup = @new_resource.backup + @cookbook = @new_resource.cookbook + @group = @new_resource.group + @mode = @new_resource.mode + @owner = @new_resource.owner + @path = @new_resource.path + @source = @new_resource.source + @content = content? + end + + def action_create + manage_plist(:create) + end + + def action_create_if_missing + manage_plist(:create_if_missing) + end + + def action_delete + # If you delete a service you want to make sure its not loaded or + # the service will be in memory and you wont be able to stop it. + if ::File.exists?(@path) + manage_service(:disable) + end + manage_plist(:delete) + end + + def action_enable + if manage_plist(:create) + manage_service(:restart) + else + manage_service(:enable) + end + end + + def action_disable + manage_service(:disable) + end + + def manage_plist(action) + if @source + res = cookbook_file_resource + elsif + res = file_resource + end + res.run_action(action) + new_resource.updated_by_last_action(true) if res.updated? + res.updated + end + + def manage_service(action) + res = service_resource + res.run_action(action) + new_resource.updated_by_last_action(true) if res.updated? + end + + def service_resource + res = Chef::Resource::MacosxService.new(@label, run_context) + res.name(@label) + res.service_name(@label) + res.plist(@path) + res.session_type(@session_type) if @session_type + + res + end + + def file_resource + res = Chef::Resource::File.new(@path, run_context) + res.name(@path) + res.backup(@backup) if @backup + res.content(@content) if @content + res.group(@group) if @group + res.mode(@mode) if @mode + res.owner(@owner) if @owner + res.source(@source) if @source + + res + end + + def cookbook_file_resource + res = Chef::Resource::CookbookFile.new(@path, run_context) + res.name(@path) + res.backup(@backup) if @backup + res.content(@content) if @content + res.cookbook_name = @cookbook if @cookbook + res.group(@group) if @group + res.mode(@mode) if @mode + res.owner(@owner) if @owner + res.source(@source) if @source + + res + end + + def define_resource_requirements + super + requirements.assert( + :create, :create_if_missing, :delete, :enable, :disable + ) do |a| + type = @new_resource.type.to_s + a.assertion { !['daemon', 'agent'].include?(type) } + a.failure_message( + Chef::Exceptions::UnsupportedAction, + "service_type must be 'daemon' or 'agent'" + ) + end + end + + private + + def content? + if @new_resource.hash + @new_resource.hash.to_plist + elsif @new_resource.program || @new_resource.program_arguments + gen_plist + end + end + + def gen_plist + plist_hash = {} + { + 'label' => 'Label', + 'program' => 'Program', + 'program_arguments' => 'ProgramArguments', + 'abandon_process_group' => 'AbandonProcessGroup', + 'debug' => 'Debug', + 'disabled' => 'Disabled', + 'enable_globbing' => 'EnableGlobbing', + 'enable_transactions' => 'EnableTransactions', + 'environment_variables' => 'EnvironmentVariables', + 'exit_timeout' => 'ExitTimeout', + 'ld_group' => 'GroupName', + 'hard_resource_limits' => 'HardreSourceLimits', + 'inetd_compatibility' => 'inetdCompatibility', + 'init_groups' => 'InitGroups', + 'keep_alive' => 'KeepAlive', + 'launch_only_once' => 'LaunchOnlyOnce', + 'limit_load_from_hosts' => 'LimitLoadFromHosts', + 'limit_load_to_hosts' => 'LimitLoadToHosts', + 'limit_load_to_session_type' => 'LimitLoadToSessionType', + 'low_priority_io' => 'LowPriorityIO', + 'mach_services' => 'MachServices', + 'nice' => 'Nice', + 'on_demand' => 'OnDemand', + 'process_type' => 'ProcessType', + 'queue_directories' => 'QueueDirectories', + 'root_directory' => 'RootDirectory', + 'run_at_load' => 'RunAtLoad', + 'sockets' => 'Sockets', + 'soft_resource_limits' => 'SoftResourceLimits', + 'standard_error_path' => 'StandardErrorPath', + 'standard_in_path' => 'StandardInPath', + 'standard_out_path' => 'StandardOutPath', + 'start_calendar_interval' => 'StartCalendarInterval', + 'start_interval' => 'StartInterval', + 'start_on_mount' => 'StartOnMount', + 'throttle_interval' => 'ThrottleInterval', + 'time_out' => 'TimeOut', + 'umask' => 'Umask', + 'username' => 'UserName', + 'wait_for_debugger' => 'WaitForDebugger', + 'watch_paths' => 'WatchPaths', + 'working_directory' => 'WorkingDirectory', + }.each do |key, val| + if @new_resource.send(key) + plist_hash[val] = @new_resource.send(key) + end + end + plist_hash.to_plist + end + + end + end +end diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb index 8af25b4c40..ceb4494b1a 100644 --- a/lib/chef/providers.rb +++ b/lib/chef/providers.rb @@ -35,6 +35,7 @@ require "chef/provider/git" require "chef/provider/group" require "chef/provider/http_request" require "chef/provider/ifconfig" +require 'chef/provider/launchd' require "chef/provider/link" require "chef/provider/log" require "chef/provider/ohai" diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb new file mode 100644 index 0000000000..44ceaf33f9 --- /dev/null +++ b/lib/chef/resource/launchd.rb @@ -0,0 +1,402 @@ +# +# Author:: Mike Dodge () +# Copyright:: Copyright (c) 2015 Facebook, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'chef/resource' +require 'chef/provider/launchd' + +class Chef + class Resource + class Launchd < Chef::Resource + provides :launchd, os: "darwin" + + identity_attr :label + + default_action :create + allowed_actions :create, :create_if_missing, :delete, :enable, :disable + + def initialize(name, run_context = nil) + super + @provider = Chef::Provider::Launchd + @resource_name = :launchd + @label = name + @disabled = false + @type = 'daemon' + @path = "/Library/LaunchDaemons/#{name}.plist" + end + + def label(arg = nil) + set_or_return( + :label, arg, + :kind_of => String + ) + end + + def source(arg = nil) + set_or_return( + :source, arg, + :kind_of => [ String, Array ] + ) + end + + def cookbook(arg = nil) + set_or_return( + :cookbook, arg, + :kind_of => String + ) + end + + def path(arg = nil) + set_or_return( + :path, arg, + :kind_of => String + ) + end + + def hash(arg = nil) + set_or_return( + :hash, arg, + :kind_of => Hash + ) + end + + def backup(arg=nil) + set_or_return( + :backup, arg, + :kind_of => [ Integer, FalseClass ] + ) + end + + def group(arg = nil) + set_or_return( + :group, arg, + :kind_of => [ String, Integer ] + ) + end + + def mode(arg = nil) + set_or_return( + :mode, arg, + :kind_of => [ String, Integer ] + ) + end + + def owner(arg = nil) + set_or_return( + :owner, arg, + :kind_of => [ String, Integer ] + ) + end + + def type(type = nil) + type = type ? type.downcase : nil + if type == 'daemon' + @path = "/Library/LaunchDaemons/#{name}.plist" + elsif type == 'agent' + @path = "/Library/LaunchAgents/#{name}.plist" + end + end + + def abandon_process_group(arg = nil) + set_or_return( + :abandon_process_group, arg, + :kind_of => String + ) + end + + def debug(arg = nil) + set_or_return( + :debug, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def disabled(arg = nil) + set_or_return( + :disabled, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def enable_globbing(arg = nil) + set_or_return( + :enable_globbing, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def enable_transactions(arg = nil) + set_or_return( + :enable_transactions, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def environment_variables(arg = nil) + set_or_return( + :environment_variables, arg, + :kind_of => Hash + ) + end + + def exit_timeout(arg = nil) + set_or_return( + :exit_timeout, arg, + :kind_of => Integer + ) + end + + def hard_resource_limits(arg = nil) + set_or_return( + :hardre_source_limits, arg, + :kind_of => Hash + ) + end + + def keep_alive(arg = nil) + set_or_return( + :keep_alive, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def launch_only_once(arg = nil) + set_or_return( + :launch_only_once, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def limit_load_from_hosts(arg = nil) + set_or_return( + :limit_load_from_hosts, arg, + :kind_of => Array + ) + end + + def limit_load_to_hosts(arg = nil) + set_or_return( + :limit_load_to_hosts, arg, + :kind_of => Array + ) + end + + def limit_load_to_session_type(arg = nil) + set_or_return( + :limit_load_to_session_type, arg, + :kind_of => String + ) + end + + def low_priority_io(arg = nil) + set_or_return( + :low_priority_io, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def mach_services(arg = nil) + set_or_return( + :mach_services, arg, + :kind_of => Hash + ) + end + + def nice(arg = nil) + set_or_return( + :nice, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def on_demand(arg = nil) + set_or_return( + :on_demand, arg, + :kind_of => String + ) + end + + def username(arg = nil) + set_or_return( + :username, arg, + :kind_of => String + ) + end + + def ld_group(arg = nil) + set_or_return( + :ld_group, arg, + :kind_of => String + ) + end + + def inetd_compatibility(arg = nil) + set_or_return( + :inetd_compatibility, arg, + :kind_of => Hash + ) + end + + def init_groups(arg = nil) + set_or_return( + :init_groups, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def process_type(arg = nil) + set_or_return( + :process_type, arg, + :kind_of => String + ) + end + + def program(arg = nil) + set_or_return( + :program, arg, + :kind_of => String + ) + end + + def program_arguments(arg = nil) + set_or_return( + :program_arguments, arg, + :kind_of => Array + ) + end + + def queue_directories(arg = nil) + set_or_return( + :queue_directories, arg, + :kind_of => Array + ) + end + + def root_directory(arg = nil) + set_or_return( + :root_directory, arg, + :kind_of => String + ) + end + + def run_at_load(arg = nil) + set_or_return( + :run_at_load, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def sockets(arg = nil) + set_or_return( + :sockets, arg, + :kind_of => Hash + ) + end + + def soft_resource_limits(arg = nil) + set_or_return( + :soft_resource_limits, arg, + :kind_of => Array + ) + end + + def standard_error_path(arg = nil) + set_or_return( + :standard_error_path, arg, + :kind_of => String + ) + end + + def standard_in_path(arg = nil) + set_or_return( + :standard_in_path, arg, + :kind_of => String + ) + end + + def standard_out_path(arg = nil) + set_or_return( + :standard_out_path, arg, + :kind_of => String + ) + end + + def start_calendar_interval(arg = nil) + set_or_return( + :start_calendar_interval, arg, + :kind_of => Hash + ) + end + + def start_interval(arg = nil) + set_or_return( + :start_interval, arg, + :kind_of => Integer + ) + end + + def start_on_mount(arg = nil) + set_or_return( + :start_on_mount, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def throttle_interval(arg = nil) + set_or_return( + :throttle_interval, arg, + :kind_of => Integer + ) + end + + def time_out(arg = nil) + set_or_return( + :time_out, arg, + :kind_of => Integer + ) + end + + def umask(arg = nil) + set_or_return( + :umask, arg, + :kind_of => Integer + ) + end + + def wait_for_debugger(arg = nil) + set_or_return( + :wait_for_debugger, arg, + :kind_of => [TrueClass, FalseClass] + ) + end + + def watch_paths(arg = nil) + set_or_return( + :watch_paths, arg, + :kind_of => Array + ) + end + + def working_directory(arg = nil) + set_or_return( + :working_directory, arg, + :kind_of => String + ) + end + end + end +end diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb index 71fe281e24..48514c975f 100644 --- a/lib/chef/resources.rb +++ b/lib/chef/resources.rb @@ -46,6 +46,7 @@ require "chef/resource/http_request" require "chef/resource/homebrew_package" require "chef/resource/ifconfig" require "chef/resource/ksh" +require 'chef/resource/launchd' require "chef/resource/link" require "chef/resource/log" require "chef/resource/macports_package" @@ -85,3 +86,10 @@ require "chef/resource/yum_package" require "chef/resource/lwrp_base" require "chef/resource/bff_package" require "chef/resource/zypper_package" + +begin + # Optional resources chef_node, chef_client, machine, machine_image, etc. + require 'cheffish' + require 'chef/provisioning' +rescue LoadError +end -- cgit v1.2.1