diff options
Diffstat (limited to 'lib/chef/provider/systemd_unit.rb')
-rw-r--r-- | lib/chef/provider/systemd_unit.rb | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb new file mode 100644 index 0000000000..db71a6c234 --- /dev/null +++ b/lib/chef/provider/systemd_unit.rb @@ -0,0 +1,210 @@ +# +# Author:: Nathan Williams (<nath.e.will@gmail.com>) +# Copyright:: Copyright 2016, Nathan Williams +# 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/mixin/which" +require "chef/mixin/shell_out" +require "chef/resource/file" + +class Chef + class Provider + class SystemdUnit < Chef::Provider + include Chef::Mixin::Which + include Chef::Mixin::ShellOut + + provides :systemd_unit, os: "linux" + + def load_current_resource + @current_resource = Chef::Resource::SystemdUnit.new(new_resource.name) + + current_resource.content(::File.read(unit_path)) if ::File.exist?(unit_path) + current_resource.user(new_resource.user) + current_resource.enabled(enabled?) + current_resource.active(active?) + current_resource.masked(masked?) + current_resource.static(static?) + current_resource.triggers_reload(new_resource.triggers_reload) + + current_resource + end + + def action_create + if current_resource.content != new_resource.to_ini + converge_by("creating unit: #{new_resource.name}") do + manage_unit_file(:create) + daemon_reload if new_resource.triggers_reload + end + end + end + + def action_delete + if ::File.exist?(unit_path) + converge_by("deleting unit: #{new_resource.name}") do + manage_unit_file(:delete) + daemon_reload if new_resource.triggers_reload + end + end + end + + def action_enable + if current_resource.static + Chef::Log.debug("#{new_resource.name} is a static unit, enabling is a NOP.") + end + + unless current_resource.enabled || current_resource.static + converge_by("enabling unit: #{new_resource.name}") do + systemctl_execute!(:enable, new_resource.name) + end + end + end + + def action_disable + if current_resource.static + Chef::Log.debug("#{new_resource.name} is a static unit, disabling is a NOP.") + end + + if current_resource.enabled && !current_resource.static + converge_by("disabling unit: #{new_resource.name}") do + systemctl_execute!(:disable, new_resource.name) + end + end + end + + def action_mask + unless current_resource.masked + converge_by("masking unit: #{new_resource.name}") do + systemctl_execute!(:mask, new_resource.name) + end + end + end + + def action_unmask + if current_resource.masked + converge_by("unmasking unit: #{new_resource.name}") do + systemctl_execute!(:unmask, new_resource.name) + end + end + end + + def action_start + unless current_resource.active + converge_by("starting unit: #{new_resource.name}") do + systemctl_execute!(:start, new_resource.name) + end + end + end + + def action_stop + if current_resource.active + converge_by("stopping unit: #{new_resource.name}") do + systemctl_execute!(:stop, new_resource.name) + end + end + end + + def action_restart + converge_by("restarting unit: #{new_resource.name}") do + systemctl_execute!(:restart, new_resource.name) + end + end + + def action_reload + if current_resource.active + converge_by("reloading unit: #{new_resource.name}") do + systemctl_execute!(:reload, new_resource.name) + end + else + Chef::Log.debug("#{new_resource.name} is not active, skipping reload.") + end + end + + def active? + systemctl_execute("is-active", new_resource.name).exitstatus == 0 + end + + def enabled? + systemctl_execute("is-enabled", new_resource.name).exitstatus == 0 + end + + def masked? + systemctl_execute(:status, new_resource.name).stdout.include?("masked") + end + + def static? + systemctl_execute("is-enabled", new_resource.name).stdout.include?("static") + end + + private + + def unit_path + if new_resource.user + "/etc/systemd/user/#{new_resource.name}" + else + "/etc/systemd/system/#{new_resource.name}" + end + end + + def manage_unit_file(action = :nothing) + Chef::Resource::File.new(unit_path, run_context).tap do |f| + f.owner "root" + f.group "root" + f.mode "0644" + f.content new_resource.to_ini + end.run_action(action) + end + + def daemon_reload + shell_out_with_systems_locale!("#{systemctl_path} daemon-reload") + end + + def systemctl_execute!(action, unit) + shell_out_with_systems_locale!("#{systemctl_cmd} #{action} #{unit}", systemctl_opts) + end + + def systemctl_execute(action, unit) + shell_out("#{systemctl_cmd} #{action} #{unit}", systemctl_opts) + end + + def systemctl_cmd + @systemctl_cmd ||= "#{systemctl_path} #{systemctl_args}" + end + + def systemctl_path + @systemctl_path ||= which("systemctl") + end + + def systemctl_args + @systemctl_args ||= new_resource.user ? "--user" : "--system" + end + + def systemctl_opts + @systemctl_opts ||= + if new_resource.user + { + "user" => new_resource.user, + "environment" => { + "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{node['etc']['passwd'][new_resource.user]['uid']}/bus", + }, + } + else + {} + end + end + end + end +end |