summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Dibowitz <phil@ipom.com>2016-03-03 02:24:05 -0800
committerPhil Dibowitz <phil@ipom.com>2016-03-03 02:24:05 -0800
commitec5a2c807e0aa06f074305a0f3047d40255831de (patch)
tree3c1640ccb3bca6f4759df65791b444b62f5691d6
parenta4d98365c1d68d7a24fba62783538951d2bbd2e0 (diff)
parente0c3ca2ac62421b656ad52aabfd1c68dd9b67433 (diff)
downloadchef-ec5a2c807e0aa06f074305a0f3047d40255831de.tar.gz
Merge pull request #4307 from davide125/systemd-mask
Extend service resource to support masking
-rw-r--r--lib/chef/provider/service.rb38
-rw-r--r--lib/chef/provider/service/systemd.rb16
-rw-r--r--lib/chef/resource/service.rb15
-rw-r--r--spec/unit/provider/service/systemd_service_spec.rb65
4 files changed, 132 insertions, 2 deletions
diff --git a/lib/chef/provider/service.rb b/lib/chef/provider/service.rb
index d716e44342..b848d33083 100644
--- a/lib/chef/provider/service.rb
+++ b/lib/chef/provider/service.rb
@@ -1,5 +1,6 @@
#
# Author:: AJ Christensen (<aj@hjksolutions.com>)
+# Author:: Davide Cavalca (<dcavalca@fb.com>)
# Copyright:: Copyright 2008-2016, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
@@ -56,6 +57,9 @@ class Chef
if @new_resource.running.nil?
@new_resource.running(@current_resource.running)
end
+ if @new_resource.masked.nil?
+ @new_resource.masked(@current_resource.masked)
+ end
end
def shared_resource_requirements
@@ -97,6 +101,32 @@ class Chef
@new_resource.enabled(false)
end
+ def action_mask
+ if @current_resource.masked
+ Chef::Log.debug("#{@new_resource} already masked - nothing to do")
+ else
+ converge_by("mask service #{@new_resource}") do
+ mask_service
+ Chef::Log.info("#{@new_resource} masked")
+ end
+ end
+ load_new_resource_state
+ @new_resource.masked(true)
+ end
+
+ def action_unmask
+ if @current_resource.masked
+ converge_by("unmask service #{@new_resource}") do
+ unmask_service
+ Chef::Log.info("#{@new_resource} unmasked")
+ end
+ else
+ Chef::Log.debug("#{@new_resource} already unmasked - nothing to do")
+ end
+ load_new_resource_state
+ @new_resource.masked(false)
+ end
+
def action_start
unless @current_resource.running
converge_by("start service #{@new_resource}") do
@@ -150,6 +180,14 @@ class Chef
raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :disable"
end
+ def mask_service
+ raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :mask"
+ end
+
+ def unmask_service
+ raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :unmask"
+ end
+
def start_service
raise Chef::Exceptions::UnsupportedAction, "#{self} does not support :start"
end
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index e70576fea7..7f90172edb 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -1,5 +1,6 @@
#
# Author:: Stephen Haynes (<sh@nomitor.com>)
+# Author:: Davide Cavalca (<dcavalca@fb.com>)
# Copyright:: Copyright 2011-2016, Chef Software Inc.
# License:: Apache License, Version 2.0
#
@@ -48,12 +49,14 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
@status_check_success = false
current_resource.running(false)
current_resource.enabled(false)
+ current_resource.masked(false)
end
else
current_resource.running(is_active?)
end
current_resource.enabled(is_enabled?)
+ current_resource.masked(is_masked?)
current_resource
end
@@ -119,6 +122,14 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
shell_out!("#{systemctl_path} disable #{new_resource.service_name}")
end
+ def mask_service
+ shell_out!("#{systemctl_path} mask #{new_resource.service_name}")
+ end
+
+ def unmask_service
+ shell_out!("#{systemctl_path} unmask #{new_resource.service_name}")
+ end
+
def is_active?
shell_out("#{systemctl_path} is-active #{new_resource.service_name} --quiet").exitstatus == 0
end
@@ -127,6 +138,11 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
shell_out("#{systemctl_path} is-enabled #{new_resource.service_name} --quiet").exitstatus == 0
end
+ def is_masked?
+ s = shell_out("#{systemctl_path} is-enabled #{new_resource.service_name}")
+ s.exitstatus != 0 && s.stdout.include?("masked")
+ end
+
private
def systemctl_path
diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb
index 849afebad0..860d5b05ff 100644
--- a/lib/chef/resource/service.rb
+++ b/lib/chef/resource/service.rb
@@ -24,16 +24,18 @@ class Chef
class Service < Chef::Resource
identity_attr :service_name
- state_attrs :enabled, :running
+ state_attrs :enabled, :running, :masked
default_action :nothing
- allowed_actions :enable, :disable, :start, :stop, :restart, :reload
+ allowed_actions :enable, :disable, :start, :stop, :restart, :reload,
+ :mask, :unmask
def initialize(name, run_context = nil)
super
@service_name = name
@enabled = nil
@running = nil
+ @masked = nil
@parameters = nil
@pattern = service_name
@start_command = nil
@@ -140,6 +142,15 @@ class Chef
)
end
+ # if the service is masked or not
+ def masked(arg = nil)
+ set_or_return(
+ :masked,
+ arg,
+ :kind_of => [ TrueClass, FalseClass ]
+ )
+ end
+
# Priority arguments can have two forms:
#
# - a simple number, in which the default start runlevels get
diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb
index b445d93aeb..cf76fdd07b 100644
--- a/spec/unit/provider/service/systemd_service_spec.rb
+++ b/spec/unit/provider/service/systemd_service_spec.rb
@@ -1,5 +1,6 @@
#
# Author:: Stephen Haynes (<sh@nomitor.com>)
+# Author:: Davide Cavalca (<dcavalca@fb.com>)
# Copyright:: Copyright 2011-2016, Chef Software Inc.
# License:: Apache License, Version 2.0
#
@@ -51,6 +52,7 @@ describe Chef::Provider::Service::Systemd do
before(:each) 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)
end
it "should create a current resource with the name of the new resource" do
@@ -127,6 +129,23 @@ describe Chef::Provider::Service::Systemd do
expect(current_resource.enabled).to be false
end
+ it "should check if the service is masked" do
+ expect(provider).to receive(:is_masked?)
+ provider.load_current_resource
+ end
+
+ it "should set masked to true if the service is masked" do
+ allow(provider).to receive(:is_masked?).and_return(true)
+ provider.load_current_resource
+ expect(current_resource.masked).to be true
+ end
+
+ it "should set masked to false if the service is not masked" do
+ allow(provider).to receive(:is_masked?).and_return(false)
+ provider.load_current_resource
+ expect(current_resource.masked).to be false
+ end
+
it "should return the current resource" do
expect(provider.load_current_resource).to eql(current_resource)
end
@@ -239,6 +258,24 @@ describe Chef::Provider::Service::Systemd do
end
end
+ describe "mask and unmask service" 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}")
+ 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)
+ 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)
+ provider.unmask_service
+ end
+ end
+
describe "is_active?" do
before(:each) do
provider.current_resource = current_resource
@@ -274,6 +311,34 @@ describe Chef::Provider::Service::Systemd do
expect(provider.is_enabled?).to be false
end
end
+
+ describe "is_masked?" 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}")
+ 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))
+ 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))
+ 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))
+ 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))
+ expect(provider.is_masked?).to be false
+ end
+ end
end
end
end