diff options
author | John McCrae <john.mccrae@progress.com> | 2022-06-14 12:40:55 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-14 12:40:55 -0700 |
commit | 675350f6d876d0ab5aac31470edb4c7fbe8dc8db (patch) | |
tree | 70368f1a7b7948ffebb45b90544c4f642b571673 | |
parent | 0959eefcd44308ad4aed63769e25eb4b4856ce04 (diff) | |
parent | fa552fab9be9551dbc8f06f98c35a28b21fe7d82 (diff) | |
download | chef-675350f6d876d0ab5aac31470edb4c7fbe8dc8db.tar.gz |
Merge pull request #12182 from chef/manick/11638_zypper_package_source_addition
-rw-r--r-- | lib/chef/provider/package/zypper.rb | 50 | ||||
-rw-r--r-- | lib/chef/provider/package/zypper/version.rb | 60 | ||||
-rw-r--r-- | spec/functional/resource/zypper_package_spec.rb | 12 | ||||
-rw-r--r-- | spec/unit/provider/package/zypper_spec.rb | 32 |
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 |