summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Dibowitz <phil@ipom.com>2019-11-01 17:59:04 -0700
committerPhil Dibowitz <phil@ipom.com>2019-11-04 15:46:07 -0800
commitd1305e8f114f89bf4a518afbdebba23544f73fd5 (patch)
tree7f0d35902dc6168dfef292dd838167a0eb257562
parenta16e94afeefe34abe1c57e6c4f44e25721db7082 (diff)
downloadchef-d1305e8f114f89bf4a518afbdebba23544f73fd5.tar.gz
Fix enable on indirect units
This follows this `is_masked` path to ensure we don't try to enable OR disable systemd units if they are indirect Fixes #9041 Signed-off-by: Phil Dibowitz <phil@ipom.com>
-rw-r--r--lib/chef/provider/service/systemd.rb16
-rw-r--r--lib/chef/provider/systemd_unit.rb16
-rw-r--r--lib/chef/resource/service.rb3
-rw-r--r--lib/chef/resource/systemd_unit.rb1
-rw-r--r--spec/unit/provider/service/systemd_service_spec.rb28
-rw-r--r--spec/unit/provider/systemd_unit_spec.rb57
6 files changed, 113 insertions, 8 deletions
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 565668c081..3b190f0153 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -51,6 +51,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
current_resource.running(false)
current_resource.enabled(false)
current_resource.masked(false)
+ current_resource.indirect(false)
end
else
current_resource.running(is_active?)
@@ -58,6 +59,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
current_resource.enabled(is_enabled?)
current_resource.masked(is_masked?)
+ current_resource.indirect(is_indirect?)
current_resource
end
@@ -143,11 +145,19 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
end
def enable_service
+ if current_resource.masked || current_resource.indirect
+ logger.trace("#{new_resource} cannot be enabled: it is masked or indirect")
+ return
+ end
options, args = get_systemctl_options_args
shell_out!("#{systemctl_path} #{args} enable #{Shellwords.escape(new_resource.service_name)}", **options)
end
def disable_service
+ if current_resource.masked || current_resource.indirect
+ logger.trace("#{new_resource} cannot be disabled: it is masked or indirect")
+ return
+ end
options, args = get_systemctl_options_args
shell_out!("#{systemctl_path} #{args} disable #{Shellwords.escape(new_resource.service_name)}", **options)
end
@@ -172,6 +182,12 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
shell_out("#{systemctl_path} #{args} is-enabled #{Shellwords.escape(new_resource.service_name)} --quiet", **options).exitstatus == 0
end
+ def is_indirect?
+ options, args = get_systemctl_options_args
+ s = shell_out("#{systemctl_path} #{args} is-enabled #{Shellwords.escape(new_resource.service_name)}", **options)
+ s.stdout.include?("indirect")
+ end
+
def is_masked?
options, args = get_systemctl_options_args
s = shell_out("#{systemctl_path} #{args} is-enabled #{Shellwords.escape(new_resource.service_name)}", **options)
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb
index 81a56d959a..3b05fb05e2 100644
--- a/lib/chef/provider/systemd_unit.rb
+++ b/lib/chef/provider/systemd_unit.rb
@@ -42,6 +42,7 @@ class Chef
current_resource.active(active?)
current_resource.masked(masked?)
current_resource.static(static?)
+ current_resource.indirect(indirect?)
current_resource.triggers_reload(new_resource.triggers_reload)
current_resource
@@ -90,8 +91,11 @@ class Chef
if current_resource.static
logger.trace("#{new_resource.unit_name} is a static unit, enabling is a NOP.")
end
+ if current_resource.indirect
+ logger.trace("#{new_resource.unit_name} is an indirect unit, enabling is a NOP.")
+ end
- unless current_resource.enabled || current_resource.static
+ unless current_resource.enabled || current_resource.static || current_resource.indirect
converge_by("enabling unit: #{new_resource.unit_name}") do
systemctl_execute!(:enable, new_resource.unit_name)
end
@@ -103,7 +107,11 @@ class Chef
logger.trace("#{new_resource.unit_name} is a static unit, disabling is a NOP.")
end
- if current_resource.enabled && !current_resource.static
+ if current_resource.indirect
+ logger.trace("#{new_resource.unit_name} is an indirect unit, enabling is a NOP.")
+ end
+
+ if current_resource.enabled && !current_resource.static && !current_resource.indirect
converge_by("disabling unit: #{new_resource.unit_name}") do
systemctl_execute!(:disable, new_resource.unit_name)
end
@@ -198,6 +206,10 @@ class Chef
systemctl_execute("is-enabled", new_resource.unit_name).stdout.include?("static")
end
+ def indirect?
+ systemctl_execute("is-enabled", new_resource.unit_name).stdout.include?("indirect")
+ end
+
private
def unit_path
diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb
index dec7209fd0..89f2a7184b 100644
--- a/lib/chef/resource/service.rb
+++ b/lib/chef/resource/service.rb
@@ -90,6 +90,9 @@ class Chef
# if the service is masked or not
property :masked, [ TrueClass, FalseClass ], skip_docs: true
+ # if the service is indirect or not
+ property :indirect, [ TrueClass, FalseClass ], skip_docs: true
+
property :options, [ Array, String ],
description: "Solaris platform only. Options to pass to the service command. See the svcadm manual for details of possible options.",
coerce: proc { |x| x.respond_to?(:split) ? x.shellsplit : x }
diff --git a/lib/chef/resource/systemd_unit.rb b/lib/chef/resource/systemd_unit.rb
index 973fdf9491..a4f087b220 100644
--- a/lib/chef/resource/systemd_unit.rb
+++ b/lib/chef/resource/systemd_unit.rb
@@ -43,6 +43,7 @@ class Chef
property :active, [TrueClass, FalseClass], skip_docs: true
property :masked, [TrueClass, FalseClass], skip_docs: true
property :static, [TrueClass, FalseClass], skip_docs: true
+ property :indirect, [TrueClass, FalseClass], skip_docs: true
# User-provided properties
property :user, String, desired_state: false,
diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb
index 15b79922b0..983d524d25 100644
--- a/spec/unit/provider/service/systemd_service_spec.rb
+++ b/spec/unit/provider/service/systemd_service_spec.rb
@@ -36,11 +36,11 @@ describe Chef::Provider::Service::Systemd do
let(:provider) { Chef::Provider::Service::Systemd.new(new_resource, run_context) }
let(:shell_out_success) do
- double("shell_out", exitstatus: 0, error?: false)
+ double("shell_out", exitstatus: 0, error?: false, stdout: "")
end
let(:shell_out_failure) do
- double("shell_out", exitstatus: 1, error?: true)
+ double("shell_out", exitstatus: 1, error?: true, stdout: "")
end
let(:current_resource) { Chef::Resource::Service.new(service_name) }
@@ -56,6 +56,7 @@ describe Chef::Provider::Service::Systemd do
allow(provider).to receive(:is_active?).and_return(false)
allow(provider).to receive(:is_enabled?).and_return(false)
allow(provider).to receive(:is_masked?).and_return(false)
+ allow(provider).to receive(:is_indirect?).and_return(false)
end
it "should create a current resource with the name of the new resource" do
@@ -359,6 +360,29 @@ describe Chef::Provider::Service::Systemd do
expect(provider.is_masked?).to be false
end
end
+
+ describe "is_indirect?" do
+ before(:each) do
+ provider.current_resource = current_resource
+ current_resource.service_name(service_name)
+ allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s)
+ end
+
+ it "should return true if '#{systemctl_path} --system is-enabled service_name' returns 'indirect'" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name_escaped}", {}).and_return(double(stdout: "indirect", exitstatus: shell_out_success))
+ expect(provider.is_indirect?).to be true
+ end
+
+ it "should return false if '#{systemctl_path} --system is-enabled service_name' returns 0 and outputs something other than 'indirect'" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name_escaped}", {}).and_return(double(stdout: "enabled", exitstatus: shell_out_success))
+ expect(provider.is_indirect?).to be false
+ end
+
+ it "should return false if '#{systemctl_path} --system is-enabled service_name' returns anything except 0 and outputs somethign other than 'indirect''" do
+ expect(provider).to receive(:shell_out).with("#{systemctl_path} --system is-enabled #{service_name_escaped}", {}).and_return(double(stdout: "enabled", exitstatus: shell_out_failure))
+ expect(provider.is_indirect?).to be false
+ end
+ end
end
end
end
diff --git a/spec/unit/provider/systemd_unit_spec.rb b/spec/unit/provider/systemd_unit_spec.rb
index 899d3dc87e..cf26c99b77 100644
--- a/spec/unit/provider/systemd_unit_spec.rb
+++ b/spec/unit/provider/systemd_unit_spec.rb
@@ -65,11 +65,19 @@ describe Chef::Provider::SystemdUnit do
end
let(:shell_out_masked) do
- double("shell_out", exit_status: 0, error?: false, stdout: "masked")
+ double("shell_out", exitstatus: 0, error?: false, stdout: "masked")
end
let(:shell_out_static) do
- double("shell_out", exit_status: 0, error?: false, stdout: "static")
+ double("shell_out", exitstatus: 0, error?: false, stdout: "static")
+ end
+
+ let(:shell_out_disabled) do
+ double("shell_out", exitstatus: 1, error?: true, stdout: "disabled")
+ end
+
+ let(:shell_out_indirect) do
+ double("shell_out", exitstatus: 0, error?: true, stdout: "indirect")
end
before(:each) do
@@ -859,7 +867,7 @@ describe Chef::Provider::SystemdUnit do
current_resource.user(user_name)
expect(provider).to receive(:shell_out_compacted)
.with(systemctl_path, "--user", "is-enabled", unit_name, user_cmd_opts)
- .and_return(shell_out_failure)
+ .and_return(shell_out_disabled)
expect(provider.enabled?).to be false
end
end
@@ -875,7 +883,7 @@ describe Chef::Provider::SystemdUnit do
it "returns false when unit is not enabled" do
expect(provider).to receive(:shell_out_compacted)
.with(systemctl_path, "--system", "is-enabled", unit_name)
- .and_return(shell_out_failure)
+ .and_return(shell_out_disabled)
expect(provider.enabled?).to be false
end
end
@@ -962,6 +970,47 @@ describe Chef::Provider::SystemdUnit do
end
end
end
+
+ describe "#indirect?" do
+ before(:each) do
+ provider.current_resource = current_resource
+ allow(provider).to receive(:which).with("systemctl").and_return(systemctl_path.to_s)
+ end
+
+ context "when a user is specified" do
+ it "returns true when the unit is indirect" do
+ current_resource.user(user_name)
+ expect(provider).to receive(:shell_out_compacted)
+ .with(systemctl_path, "--user", "is-enabled", unit_name, user_cmd_opts)
+ .and_return(shell_out_indirect)
+ expect(provider.indirect?).to be true
+ end
+
+ it "returns false when the unit is not indirect" do
+ current_resource.user(user_name)
+ expect(provider).to receive(:shell_out_compacted)
+ .with(systemctl_path, "--user", "is-enabled", unit_name, user_cmd_opts)
+ .and_return(shell_out_static)
+ expect(provider.indirect?).to be false
+ end
+ end
+
+ context "when no user is specified" do
+ it "returns true when the unit is indirect" do
+ expect(provider).to receive(:shell_out_compacted)
+ .with(systemctl_path, "--system", "is-enabled", unit_name)
+ .and_return(shell_out_indirect)
+ expect(provider.indirect?).to be true
+ end
+
+ it "returns false when the unit is not indirect" do
+ expect(provider).to receive(:shell_out_compacted)
+ .with(systemctl_path, "--system", "is-enabled", unit_name)
+ .and_return(shell_out_static)
+ expect(provider.indirect?).to be false
+ end
+ end
+ end
end
end
end