summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/provider/systemd_unit.rb210
-rw-r--r--lib/chef/providers.rb1
-rw-r--r--lib/chef/resource/systemd_unit.rb61
-rw-r--r--lib/chef/resources.rb1
4 files changed, 273 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
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index a8a058158c..14c47df939 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -54,6 +54,7 @@ require "chef/provider/ruby_block"
require "chef/provider/script"
require "chef/provider/service"
require "chef/provider/subversion"
+require "chef/provider/systemd_unit"
require "chef/provider/template"
require "chef/provider/user"
require "chef/provider/whyrun_safe_ruby_block"
diff --git a/lib/chef/resource/systemd_unit.rb b/lib/chef/resource/systemd_unit.rb
new file mode 100644
index 0000000000..525e9ab35e
--- /dev/null
+++ b/lib/chef/resource/systemd_unit.rb
@@ -0,0 +1,61 @@
+#
+# 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/resource"
+require "iniparse"
+
+class Chef
+ class Resource
+ class SystemdUnit < Chef::Resource
+ resource_name :systemd_unit
+
+ default_action :nothing
+ allowed_actions :create, :delete,
+ :enable, :disable,
+ :mask, :unmask,
+ :start, :stop,
+ :restart, :reload
+
+ property :enabled, [TrueClass, FalseClass]
+ property :active, [TrueClass, FalseClass]
+ property :masked, [TrueClass, FalseClass]
+ property :static, [TrueClass, FalseClass]
+ property :user, String, desired_state: false
+ property :content, [String, Hash]
+ property :triggers_reload, [TrueClass, FalseClass],
+ default: true, desired_state: false
+
+ def to_ini
+ case content
+ when Hash
+ IniParse.gen do |doc|
+ content.each_pair do |sect, opts|
+ doc.section(sect) do |section|
+ opts.each_pair do |opt, val|
+ section.option(opt, val)
+ end
+ end
+ end
+ end.to_s
+ else
+ content.to_s
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index d8cec8c51d..af9c918f55 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -75,6 +75,7 @@ require "chef/resource/ruby_block"
require "chef/resource/scm"
require "chef/resource/script"
require "chef/resource/service"
+require "chef/resource/systemd_unit"
require "chef/resource/windows_service"
require "chef/resource/subversion"
require "chef/resource/smartos_package"