diff options
author | Phil Dibowitz <phil@ipom.com> | 2016-03-03 02:24:05 -0800 |
---|---|---|
committer | Phil Dibowitz <phil@ipom.com> | 2016-03-03 02:24:05 -0800 |
commit | ec5a2c807e0aa06f074305a0f3047d40255831de (patch) | |
tree | 3c1640ccb3bca6f4759df65791b444b62f5691d6 | |
parent | a4d98365c1d68d7a24fba62783538951d2bbd2e0 (diff) | |
parent | e0c3ca2ac62421b656ad52aabfd1c68dd9b67433 (diff) | |
download | chef-ec5a2c807e0aa06f074305a0f3047d40255831de.tar.gz |
Merge pull request #4307 from davide125/systemd-mask
Extend service resource to support masking
-rw-r--r-- | lib/chef/provider/service.rb | 38 | ||||
-rw-r--r-- | lib/chef/provider/service/systemd.rb | 16 | ||||
-rw-r--r-- | lib/chef/resource/service.rb | 15 | ||||
-rw-r--r-- | spec/unit/provider/service/systemd_service_spec.rb | 65 |
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 |