summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorc5227532 <eike.waldt@sap.com>2016-09-28 19:49:49 +0200
committerc5227532 <eike.waldt@sap.com>2016-09-28 19:49:49 +0200
commit5320cb1b139defb1a37df0a12e26fe8dad1cc8bf (patch)
tree4f70ebd4403f3613a4d8e7e856eaf529a7e097bb
parent7ed29654c4adf43efbdddd2dccc5afb014c88cca (diff)
downloadchef-5320cb1b139defb1a37df0a12e26fe8dad1cc8bf.tar.gz
implement locking
-rw-r--r--lib/chef/provider/package.rb43
-rw-r--r--lib/chef/provider/package/zypper.rb30
-rw-r--r--lib/chef/resource/package.rb2
-rw-r--r--spec/unit/provider/package/zypper_spec.rb18
-rw-r--r--spec/unit/provider/package_spec.rb37
5 files changed, 129 insertions, 1 deletions
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index 3f641145e6..5d2c85bcfe 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/package.rb
@@ -218,6 +218,41 @@ class Chef
end
end
+ def package_locked?
+ if !current_version_array.any?
+ # ! any? means it's all nil's, which means nothing is installed
+ false
+ elsif !new_version_array.any?
+ true # remove any version of all packages
+ elsif have_any_matching_version?
+ true # remove the version we have
+ else
+ false # we don't have the version we want to remove
+ end
+ end
+
+ def action_lock
+ multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
+ if package_locked(name) == true
+ Chef::Log.debug("#{new_resource} is already locked")
+ else
+ lock_package(name)
+ Chef::Log.info("#{@new_resource} locked")
+ end
+ end
+ end
+
+ def action_unlock
+ multipackage_api_adapter(@current_resource.package_name, @new_resource.version) do |name, version|
+ if package_locked(name) == false
+ Chef::Log.debug("#{new_resource} is already unlocked")
+ else
+ unlock_package(name)
+ Chef::Log.info("#{@new_resource} unlocked")
+ end
+ end
+ end
+
# @todo use composition rather than inheritance
def multipackage_api_adapter(name, version)
@@ -252,6 +287,14 @@ class Chef
raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :reconfig" )
end
+ def lock_package(name)
+ raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :lock" )
+ end
+
+ def unlock_package(name)
+ raise( Chef::Exceptions::UnsupportedAction, "#{self} does not support :unlock" )
+ end
+
# used by subclasses. deprecated. use #a_to_s instead.
def expand_options(options)
options ? " #{options}" : ""
diff --git a/lib/chef/provider/package/zypper.rb b/lib/chef/provider/package/zypper.rb
index e20a7332f7..efe07f52af 100644
--- a/lib/chef/provider/package/zypper.rb
+++ b/lib/chef/provider/package/zypper.rb
@@ -75,6 +75,28 @@ class Chef
end
end
+### def package_locked?
+### package_name_array.map do |package_name|
+#### lock = `zypper locks | grep "| #{package_name} "`.split("|").shift(2).last.strip
+### package_name.lock = `zypper locks | grep "| #{package_name} "`
+### if package_name.lock.empty?
+### false
+### else
+### true
+### end
+### end
+### end
+ def package_locked(name)
+ islocked = false
+ locked = shell_out_with_timeout!("zypper locks")
+ locked.stdout.each_line do |line|
+ if line.split('|').shift(2).last.strip == name.first
+ islocked = true
+ end
+ end
+ return islocked
+ end
+
def load_current_resource
@current_resource = Chef::Resource::ZypperPackage.new(new_resource.name)
current_resource.package_name(new_resource.package_name)
@@ -107,6 +129,14 @@ class Chef
zypper_package("remove --clean-deps", name, version)
end
+ def lock_package(name)
+ shell_out_with_timeout!(a_to_s("zypper", "addlock", name))
+ end
+
+ def unlock_package(name)
+ shell_out_with_timeout!(a_to_s("zypper", "removelock", name))
+ end
+
private
def zip(names, versions)
diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb
index 32339e1a24..0738107339 100644
--- a/lib/chef/resource/package.rb
+++ b/lib/chef/resource/package.rb
@@ -25,7 +25,7 @@ class Chef
resource_name :package
default_action :install
- allowed_actions :install, :upgrade, :remove, :purge, :reconfig
+ allowed_actions :install, :upgrade, :remove, :purge, :reconfig, :lock, :unlock
def initialize(name, *args)
# We capture name here, before it gets coerced to name
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index 8838c26b71..c64b113649 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -231,6 +231,24 @@ describe Chef::Provider::Package::Zypper do
end
end
+ describe "lock_package" do
+ it "should run zypper addlock with the package name" do
+ shell_out_expectation!(
+ "zypper addlock emacs"
+ )
+ provider.lock_package(["emacs"])
+ end
+ end
+
+ describe "unlock_package" do
+ it "should run zypper removelock with the package name" do
+ shell_out_expectation!(
+ "zypper removelock emacs"
+ )
+ provider.unlock_package(["emacs"])
+ end
+ end
+
describe "on an older zypper" do
before(:each) do
allow(provider).to receive(:`).and_return("0.11.6")
diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb
index 40b7516b5c..082fc00ba5 100644
--- a/spec/unit/provider/package_spec.rb
+++ b/spec/unit/provider/package_spec.rb
@@ -321,6 +321,35 @@ describe Chef::Provider::Package do
end
end
+ describe "When locking the package" do
+ before(:each) do
+ allow(provider).to receive(:lock_package).and_return(true)
+ end
+
+ it "should lock the package if it is unlocked" do
+ expect(provider).to be_locking_package
+ expect(provider).to receive(:lock_package).with("emacs")
+ provider.run_action(:lock)
+ expect(new_resource).to be_updated
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "should not purge the package if it is not installed" do
+ current_resource.instance_variable_set(:@version, nil)
+ expect(provider).not_to be_locking_package
+
+ expect(provider).not_to receive(:lock_package)
+ provider.run_action(:lock)
+ expect(new_resource).not_to be_updated_by_last_action
+ end
+
+ it "should set the resource to updated if it purges the package" do
+ provider.run_action(:lock)
+ expect(new_resource).to be_updated
+ end
+
+ end
+
describe "when running commands to be implemented by subclasses" do
it "should raises UnsupportedAction for install" do
expect { provider.install_package("emacs", "1.4.2") }.to raise_error(Chef::Exceptions::UnsupportedAction)
@@ -346,6 +375,14 @@ describe Chef::Provider::Package do
it "should raise UnsupportedAction for reconfig" do
expect { provider.reconfig_package("emacs", "1.4.2") }.to raise_error(Chef::Exceptions::UnsupportedAction)
end
+
+ it "should raise UnsupportedAction for lock" do
+ expect { provider.lock_package("emacs") }.to raise_error(Chef::Exceptions::UnsupportedAction)
+ end
+
+ it "should raise UnsupportedAction for unlock" do
+ expect { provider.unlock_package("emacs") }.to raise_error(Chef::Exceptions::UnsupportedAction)
+ end
end
describe "when given a response file" do