summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCrae <john.mccrae@progress.com>2022-06-14 12:40:55 -0700
committerGitHub <noreply@github.com>2022-06-14 12:40:55 -0700
commit675350f6d876d0ab5aac31470edb4c7fbe8dc8db (patch)
tree70368f1a7b7948ffebb45b90544c4f642b571673
parent0959eefcd44308ad4aed63769e25eb4b4856ce04 (diff)
parentfa552fab9be9551dbc8f06f98c35a28b21fe7d82 (diff)
downloadchef-675350f6d876d0ab5aac31470edb4c7fbe8dc8db.tar.gz
Merge pull request #12182 from chef/manick/11638_zypper_package_source_addition
-rw-r--r--lib/chef/provider/package/zypper.rb50
-rw-r--r--lib/chef/provider/package/zypper/version.rb60
-rw-r--r--spec/functional/resource/zypper_package_spec.rb12
-rw-r--r--spec/unit/provider/package/zypper_spec.rb32
4 files changed, 151 insertions, 3 deletions
diff --git a/lib/chef/provider/package/zypper.rb b/lib/chef/provider/package/zypper.rb
index 47e85a83d0..9cd95aade7 100644
--- a/lib/chef/provider/package/zypper.rb
+++ b/lib/chef/provider/package/zypper.rb
@@ -20,17 +20,28 @@
require_relative "../package"
require_relative "../../resource/zypper_package"
+require_relative "zypper/version"
class Chef
class Provider
class Package
class Zypper < Chef::Provider::Package
use_multipackage_api
+ use_package_name_for_source
allow_nils
provides :package, platform_family: "suse"
provides :zypper_package
+ def define_resource_requirements
+ super
+ requirements.assert(:install, :upgrade) do |a|
+ a.assertion { source_files_exist? }
+ a.failure_message Chef::Exceptions::Package, "#{new_resource} source file(s) do not exist: #{missing_sources}"
+ a.whyrun "Assuming they would have been previously created."
+ end
+ end
+
def load_current_resource
@current_resource = Chef::Resource::ZypperPackage.new(new_resource.name)
current_resource.package_name(new_resource.package_name)
@@ -70,7 +81,35 @@ class Chef
end
def candidate_version
- @candidate_version ||= package_name_array.each_with_index.map { |pkg, i| available_version(i) }
+ package_name_array.each_with_index.map do |pkg, i|
+ available_version(i)
+ end
+ end
+
+ # returns true if all sources exist. Returns false if any do not, or if no
+ # sources were specified.
+ # @return [Boolean] True if all sources exist
+ def source_files_exist?
+ if !new_resource.source.nil?
+ resolved_source_array.all? { |s| s && ::File.exist?(s) }
+ else
+ true
+ end
+ end
+
+ # Helper to return all the names of the missing sources for error messages.
+ # @return [Array<String>] Array of missing sources
+ def missing_sources
+ resolved_source_array.select { |s| s.nil? || !::File.exist?(s) }
+ end
+
+ def resolve_source_to_version
+ shell_out!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n' #{new_resource.source}").stdout.each_line do |line|
+ case line
+ when /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/
+ return Version.new($1, "#{$2 == "(none)" ? "0" : $2}:#{$3}-#{$4}", $5)
+ end
+ end
end
def resolve_current_version(package_name)
@@ -119,7 +158,12 @@ class Chef
def available_version(index)
@available_version ||= []
- @available_version[index] ||= resolve_available_version(package_name_array[index], safe_version_array[index])
+
+ @available_version[index] ||= if new_resource.source
+ resolve_source_to_version
+ else
+ resolve_available_version(package_name_array[index], safe_version_array[index])
+ end
@available_version[index]
end
@@ -141,7 +185,7 @@ class Chef
end
def zypper_package(command, global_options, *options, names, versions)
- zipped_names = zip(names, versions)
+ zipped_names = new_resource.source || zip(names, versions)
if zypper_version < 1.0
shell_out!("zypper", global_options, gpg_checks, command, *options, "-y", names)
else
diff --git a/lib/chef/provider/package/zypper/version.rb b/lib/chef/provider/package/zypper/version.rb
new file mode 100644
index 0000000000..8c430c9d66
--- /dev/null
+++ b/lib/chef/provider/package/zypper/version.rb
@@ -0,0 +1,60 @@
+#
+# Copyright:: Copyright (c) Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class Chef
+ class Provider
+ class Package
+ class Zypper < Chef::Provider::Package
+
+ # helper class to assist in passing around name/version/arch triples
+ class Version
+ attr_accessor :name
+ attr_accessor :version
+ attr_accessor :arch
+
+ def initialize(name, version, arch)
+ @name = name
+ @version = version
+ @arch = arch
+ end
+
+ def to_s
+ "#{name}-#{version}.#{arch}" unless version.nil?
+ end
+
+ def version_with_arch
+ "#{version}.#{arch}" unless version.nil?
+ end
+
+ def name_with_arch
+ "#{name}.#{arch}" unless name.nil?
+ end
+
+ def matches_name_and_arch?(other)
+ other.version == version && other.arch == arch
+ end
+
+ def ==(other)
+ name == other.name && version == other.version && arch == other.arch
+ end
+
+ alias eql? ==
+ end
+ end
+ end
+ end
+end
diff --git a/spec/functional/resource/zypper_package_spec.rb b/spec/functional/resource/zypper_package_spec.rb
index 3d3a1db786..fbf394bae8 100644
--- a/spec/functional/resource/zypper_package_spec.rb
+++ b/spec/functional/resource/zypper_package_spec.rb
@@ -74,6 +74,18 @@ describe Chef::Resource::ZypperPackage, :requires_root, :suse_only do
expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
end
+ it "install package with source argument" do
+ zypper_package.source = "#{CHEF_SPEC_ASSETS}/zypprepo/chef_rpm-1.10-1.#{pkg_arch}.rpm"
+ zypper_package.run_action(:install)
+ expect(zypper_package.updated_by_last_action?).to be true
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
+ end
+
+ it "raises an error when passed a source that does not exist" do
+ zypper_package.source = "#{CHEF_SPEC_ASSETS}/false/zypprepo/chef_rpm-1.10-1.#{pkg_arch}.rpm"
+ expect { zypper_package.run_action(:install) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
+ end
+
it "does not install if the package is installed" do
preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
zypper_package.run_action(:install)
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index a1f6629f55..2850a70560 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -32,6 +32,8 @@ describe Chef::Provider::Package::Zypper do
let(:status) { double(stdout: "\n", exitstatus: 0) }
+ let(:source) { "/tmp/wget_1.11.4-1ubuntu1_amd64.rpm" }
+
before(:each) do
allow(Chef::Resource::Package).to receive(:new).and_return(current_resource)
allow(provider).to receive(:shell_out_compacted!).and_return(status)
@@ -163,6 +165,21 @@ describe Chef::Provider::Package::Zypper do
)
provider.install_package(["emacs"], ["1.0"])
end
+
+ it "should run zypper install with source option" do
+ new_resource.source "/tmp/wget_1.11.4-1ubuntu1_amd64.rpm"
+ allow(::File).to receive(:exist?).with("/tmp/wget_1.11.4-1ubuntu1_amd64.rpm").and_return(true)
+ shell_out_expectation!(
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "/tmp/wget_1.11.4-1ubuntu1_amd64.rpm"
+ )
+ provider.install_package(["wget"], ["1.11.4-1ubuntu1_amd64"])
+ end
+
+ it "should raise an exception if a source is supplied but not found when :install" do
+ new_resource.source "/tmp/blah/wget_1.11.4-1ubuntu1_amd64.rpm"
+ allow(::File).to receive(:exist?).with(new_resource.source).and_return(false)
+ expect { provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
+ end
end
describe "upgrade_package" do
@@ -200,6 +217,21 @@ describe Chef::Provider::Package::Zypper do
)
provider.upgrade_package(["emacs"], ["1.0"])
end
+
+ it "should run zypper upgrade with source option" do
+ new_resource.source "/tmp/wget_1.11.4-1ubuntu1_amd64.rpm"
+ allow(::File).to receive(:exist?).with("/tmp/wget_1.11.4-1ubuntu1_amd64.rpm").and_return(true)
+ shell_out_expectation!(
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "/tmp/wget_1.11.4-1ubuntu1_amd64.rpm"
+ )
+ provider.upgrade_package(["wget"], ["1.11.4-1ubuntu1_amd64"])
+ end
+
+ it "should raise an exception if a source is supplied but not found when :upgrade" do
+ new_resource.source "/tmp/blah/wget_1.11.4-1ubuntu1_amd64.rpm"
+ allow(::File).to receive(:exist?).with(new_resource.source).and_return(false)
+ expect { provider.run_action(:upgrade) }.to raise_error(Chef::Exceptions::Package)
+ end
end
describe "remove_package" do