summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavide Cavalca <dcavalca@fb.com>2015-12-14 12:37:04 -0800
committerDavide Cavalca <dcavalca@fb.com>2016-03-03 09:39:01 -0800
commit0475cf75df5a186e3ef8fa62a9212f775aae30b3 (patch)
tree6d2926eff802711cb17166757572b67ac5573016
parent383e681013bdd188f208753f9be60b4b9580aa52 (diff)
downloadchef-0475cf75df5a186e3ef8fa62a9212f775aae30b3.tar.gz
Extend service resource to support systemd user services
-rw-r--r--lib/chef/provider/service/systemd.rb51
-rw-r--r--lib/chef/resource/service.rb9
-rw-r--r--spec/unit/provider/service/systemd_service_spec.rb72
3 files changed, 85 insertions, 47 deletions
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 7f90172edb..a6189e4332 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -70,6 +70,24 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
end
end
+ def get_systemctl_options_args
+ if new_resource.user
+ uid = node['etc']['passwd'][new_resource.user]['uid']
+ options = {
+ 'environment' => {
+ 'DBUS_SESSION_BUS_ADDRESS' => "unix:path=/run/user/#{uid}/bus",
+ },
+ 'user' => new_resource.user,
+ }
+ args = '--user'
+ else
+ options = {}
+ args = '--system'
+ end
+
+ return options, args
+ end
+
def start_service
if current_resource.running
Chef::Log.debug("#{new_resource} already running, not starting")
@@ -77,7 +95,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
if new_resource.start_command
super
else
- shell_out_with_systems_locale!("#{systemctl_path} start #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out_with_systems_locale!("#{systemctl_path} #{args} start #{new_resource.service_name}", options)
end
end
end
@@ -89,7 +108,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
if new_resource.stop_command
super
else
- shell_out_with_systems_locale!("#{systemctl_path} stop #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out_with_systems_locale!("#{systemctl_path} #{args} stop #{new_resource.service_name}", options)
end
end
end
@@ -98,7 +118,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
if new_resource.restart_command
super
else
- shell_out_with_systems_locale!("#{systemctl_path} restart #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out_with_systems_locale!("#{systemctl_path} #{args} restart #{new_resource.service_name}", options)
end
end
@@ -107,7 +128,8 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
super
else
if current_resource.running
- shell_out_with_systems_locale!("#{systemctl_path} reload #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out_with_systems_locale!("#{systemctl_path} #{args} reload #{new_resource.service_name}", options)
else
start_service
end
@@ -115,31 +137,38 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
end
def enable_service
- shell_out!("#{systemctl_path} enable #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out!("#{systemctl_path} #{args} enable #{new_resource.service_name}", options)
end
def disable_service
- shell_out!("#{systemctl_path} disable #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out!("#{systemctl_path} #{args} disable #{new_resource.service_name}", options)
end
def mask_service
- shell_out!("#{systemctl_path} mask #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out!("#{systemctl_path} #{args} mask #{new_resource.service_name}", options)
end
def unmask_service
- shell_out!("#{systemctl_path} unmask #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ shell_out!("#{systemctl_path} #{args} unmask #{new_resource.service_name}", options)
end
def is_active?
- shell_out("#{systemctl_path} is-active #{new_resource.service_name} --quiet").exitstatus == 0
+ options, args = get_systemctl_options_args
+ shell_out("#{systemctl_path} #{args} is-active #{new_resource.service_name} --quiet", options).exitstatus == 0
end
def is_enabled?
- shell_out("#{systemctl_path} is-enabled #{new_resource.service_name} --quiet").exitstatus == 0
+ options, args = get_systemctl_options_args
+ shell_out("#{systemctl_path} #{args} is-enabled #{new_resource.service_name} --quiet", options).exitstatus == 0
end
def is_masked?
- s = shell_out("#{systemctl_path} is-enabled #{new_resource.service_name}")
+ options, args = get_systemctl_options_args
+ s = shell_out("#{systemctl_path} #{args} is-enabled #{new_resource.service_name}", options)
s.exitstatus != 0 && s.stdout.include?("masked")
end
diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb
index 860d5b05ff..1ca4b84af0 100644
--- a/lib/chef/resource/service.rb
+++ b/lib/chef/resource/service.rb
@@ -47,6 +47,7 @@ class Chef
@priority = nil
@timeout = nil
@run_levels = nil
+ @user = nil
@supports = { :restart => nil, :reload => nil, :status => nil }
end
@@ -193,6 +194,14 @@ class Chef
:kind_of => [ Array ] )
end
+ def user(arg = nil)
+ set_or_return(
+ :user,
+ arg,
+ :kind_of => [ String ]
+ )
+ end
+
def supports(args = {})
if args.is_a? Array
args.each { |arg| @supports[arg] = true }
diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb
index cf76fdd07b..b4a5015f58 100644
--- a/spec/unit/provider/service/systemd_service_spec.rb
+++ b/spec/unit/provider/service/systemd_service_spec.rb
@@ -171,14 +171,14 @@ describe Chef::Provider::Service::Systemd do
provider.start_service
end
- it "should call '#{systemctl_path} start service_name' if no start command is specified" do
- expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} start #{service_name}").and_return(shell_out_success)
+ it "should call '#{systemctl_path} --system start service_name' if no start command is specified" do
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system start #{service_name}", {}).and_return(shell_out_success)
provider.start_service
end
- it "should not call '#{systemctl_path} start service_name' if it is already running" do
+ it "should not call '#{systemctl_path} --system start service_name' if it is already running" do
current_resource.running(true)
- expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} start #{service_name}")
+ expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system start #{service_name}", {})
provider.start_service
end
@@ -189,9 +189,9 @@ describe Chef::Provider::Service::Systemd do
provider.restart_service
end
- it "should call '#{systemctl_path} restart service_name' if no restart command is specified" do
+ it "should call '#{systemctl_path} --system restart service_name' if no restart command is specified" do
current_resource.running(true)
- expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} restart #{service_name}").and_return(shell_out_success)
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system restart #{service_name}", {}).and_return(shell_out_success)
provider.restart_service
end
@@ -206,9 +206,9 @@ describe Chef::Provider::Service::Systemd do
end
context "when a reload command is not specified" do
- it "should call '#{systemctl_path} reload service_name' if the service is running" do
+ it "should call '#{systemctl_path} --system reload service_name' if the service is running" do
current_resource.running(true)
- expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} reload #{service_name}").and_return(shell_out_success)
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system reload #{service_name}", {}).and_return(shell_out_success)
provider.reload_service
end
@@ -227,15 +227,15 @@ describe Chef::Provider::Service::Systemd do
provider.stop_service
end
- it "should call '#{systemctl_path} stop service_name' if no stop command is specified" do
+ it "should call '#{systemctl_path} --system stop service_name' if no stop command is specified" do
current_resource.running(true)
- expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} stop #{service_name}").and_return(shell_out_success)
+ expect(provider).to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system stop #{service_name}", {}).and_return(shell_out_success)
provider.stop_service
end
- it "should not call '#{systemctl_path} stop service_name' if it is already stopped" do
+ it "should not call '#{systemctl_path} --system stop service_name' if it is already stopped" do
current_resource.running(false)
- expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} stop #{service_name}")
+ expect(provider).not_to receive(:shell_out_with_systems_locale!).with("#{systemctl_path} --system stop #{service_name}", {})
provider.stop_service
end
end
@@ -247,13 +247,13 @@ describe Chef::Provider::Service::Systemd do
allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}")
end
- it "should call '#{systemctl_path} enable service_name' to enable the service" do
- expect(provider).to receive(:shell_out!).with("#{systemctl_path} enable #{service_name}").and_return(shell_out_success)
+ it "should call '#{systemctl_path} --system enable service_name' to enable the service" do
+ expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system enable #{service_name}", {}).and_return(shell_out_success)
provider.enable_service
end
- it "should call '#{systemctl_path} disable service_name' to disable the service" do
- expect(provider).to receive(:shell_out!).with("#{systemctl_path} disable #{service_name}").and_return(shell_out_success)
+ it "should call '#{systemctl_path} --system disable service_name' to disable the service" do
+ expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system disable #{service_name}", {}).and_return(shell_out_success)
provider.disable_service
end
end
@@ -265,13 +265,13 @@ describe Chef::Provider::Service::Systemd do
allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}")
end
- it "should call '#{systemctl_path} mask service_name' to mask the service" do
- expect(provider).to receive(:shell_out!).with("#{systemctl_path} mask #{service_name}").and_return(shell_out_success)
+ it "should call '#{systemctl_path} --system mask service_name' to mask the service" do
+ expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system mask #{service_name}", {}).and_return(shell_out_success)
provider.mask_service
end
- it "should call '#{systemctl_path} unmask service_name' to unmask the service" do
- expect(provider).to receive(:shell_out!).with("#{systemctl_path} unmask #{service_name}").and_return(shell_out_success)
+ it "should call '#{systemctl_path} --system unmask service_name' to unmask the service" do
+ expect(provider).to receive(:shell_out!).with("#{systemctl_path} --system unmask #{service_name}", {}).and_return(shell_out_success)
provider.unmask_service
end
end
@@ -283,13 +283,13 @@ describe Chef::Provider::Service::Systemd do
allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}")
end
- it "should return true if '#{systemctl_path} is-active service_name' returns 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-active #{service_name} --quiet").and_return(shell_out_success)
+ it "should return true if '#{systemctl_path} --system is-active service_name' returns 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-active #{service_name} --quiet", {}).and_return(shell_out_success)
expect(provider.is_active?).to be true
end
- it "should return false if '#{systemctl_path} is-active service_name' returns anything except 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-active #{service_name} --quiet").and_return(shell_out_failure)
+ it "should return false if '#{systemctl_path} --system is-active service_name' returns anything except 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-active #{service_name} --quiet", {}).and_return(shell_out_failure)
expect(provider.is_active?).to be false
end
end
@@ -301,13 +301,13 @@ describe Chef::Provider::Service::Systemd do
allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}")
end
- it "should return true if '#{systemctl_path} is-enabled service_name' returns 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name} --quiet").and_return(shell_out_success)
+ it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name} --quiet", {}).and_return(shell_out_success)
expect(provider.is_enabled?).to be true
end
- it "should return false if '#{systemctl_path} is-enabled service_name' returns anything except 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name} --quiet").and_return(shell_out_failure)
+ it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name} --quiet", {}).and_return(shell_out_failure)
expect(provider.is_enabled?).to be false
end
end
@@ -319,23 +319,23 @@ describe Chef::Provider::Service::Systemd do
allow(provider).to receive(:which).with("systemctl").and_return("#{systemctl_path}")
end
- it "should return true if '#{systemctl_path} is-enabled service_name' returns 'masked' and returns anything except 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name}").and_return(double(:stdout => "masked", :exitstatus => shell_out_failure))
+ it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 'masked' and returns anything except 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "masked", :exitstatus => shell_out_failure))
expect(provider.is_masked?).to be true
end
- it "should return true if '#{systemctl_path} is-enabled service_name' outputs 'masked-runtime' and returns anything except 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name}").and_return(double(:stdout => "masked-runtime", :exitstatus => shell_out_failure))
+ it "should return true if '#{systemctl_path} --system is-enabled service_name' outputs 'masked-runtime' and returns anything except 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "masked-runtime", :exitstatus => shell_out_failure))
expect(provider.is_masked?).to be true
end
- it "should return false if '#{systemctl_path} is-enabled service_name' returns 0" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name}").and_return(double(:stdout => "enabled", :exitstatus => shell_out_success))
+ it "should return false if '#{systemctl_path} --system is-enabled service_name' returns 0" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "enabled", :exitstatus => shell_out_success))
expect(provider.is_masked?).to be false
end
- it "should return false if '#{systemctl_path} is-enabled service_name' returns anything except 0 and outputs an error'" do
- expect(provider).to receive(:shell_out).with("#{systemctl_path} is-enabled #{service_name}").and_return(double(:stdout => "Failed to get unit file state for #{service_name}: No such file or directory", :exitstatus => shell_out_failure))
+ it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0 and outputs an error'" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name}", {}).and_return(double(:stdout => "Failed to get unit file state for #{service_name}: No such file or directory", :exitstatus => shell_out_failure))
expect(provider.is_masked?).to be false
end
end