summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2020-03-19 11:33:22 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2020-03-19 11:33:22 -0700
commit3494a29604b7719ab640a325becabbcdc57a7bce (patch)
tree0f3b806639e54f8c5b5e9a9c4df7003062d1767e
parent44ad9264d78877c99b1304f8826c208f240c1eeb (diff)
downloadchef-lcg/dnf-refresh.tar.gz
DNF refresh and aarch64-el8 supportlcg/dnf-refresh
should port all fixes from the yum provider back into the dnf provider. adds aarch for el8 since the func tests now pass. Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r--.expeditor/release.omnibus.yml1
-rw-r--r--lib/chef/provider/package/dnf.rb78
-rw-r--r--lib/chef/provider/package/dnf/dnf_helper.py110
-rw-r--r--lib/chef/provider/package/dnf/python_helper.rb117
-rw-r--r--lib/chef/provider/package/dnf/version.rb8
-rw-r--r--lib/chef/provider/package/yum.rb10
-rw-r--r--lib/chef/provider/package/yum/python_helper.rb2
-rw-r--r--spec/functional/resource/dnf_package_spec.rb599
-rw-r--r--spec/unit/provider/package/dnf/python_helper_spec.rb4
9 files changed, 684 insertions, 245 deletions
diff --git a/.expeditor/release.omnibus.yml b/.expeditor/release.omnibus.yml
index 4e365a5c7b..5e09b706ae 100644
--- a/.expeditor/release.omnibus.yml
+++ b/.expeditor/release.omnibus.yml
@@ -20,6 +20,7 @@ builder-to-testers-map:
- el-6-x86_64
el-7-aarch64:
- el-7-aarch64
+ - el-8-aarch64
el-7-ppc64:
- el-7-ppc64
el-7-ppc64le:
diff --git a/lib/chef/provider/package/dnf.rb b/lib/chef/provider/package/dnf.rb
index d7b61e0789..9044965884 100644
--- a/lib/chef/provider/package/dnf.rb
+++ b/lib/chef/provider/package/dnf.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016-2018, Chef Software Inc.
+# Copyright:: Copyright 2016-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -118,23 +118,79 @@ class Chef
flushcache
end
+ # NB: the dnf_package provider manages individual single packages, please do not submit issues or PRs to try to add wildcard
+ # support to lock / unlock. The best solution is to write an execute resource which does a not_if `dnf versionlock | grep '^pattern`` kind of approach
+ def lock_package(names, versions)
+ dnf("-d0", "-e0", "-y", options, "versionlock", "add", resolved_package_lock_names(names))
+ end
+
+ # NB: the dnf_package provider manages individual single packages, please do not submit issues or PRs to try to add wildcard
+ # support to lock / unlock. The best solution is to write an execute resource which does a only_if `dnf versionlock | grep '^pattern`` kind of approach
+ def unlock_package(names, versions)
+ # dnf versionlock delete on rhel6 needs the glob nonsense in the following command
+ dnf("-d0", "-e0", "-y", options, "versionlock", "delete", resolved_package_lock_names(names).map { |n| "*:#{n}-*" })
+ end
+
private
- def resolve_source_to_version_obj
- shell_out!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n' #{new_resource.source}").stdout.each_line do |line|
- # this is another case of committing the sin of doing some lightweight mangling of RPM versions in ruby -- but the output of the rpm command
- # does not match what the dnf library accepts.
- case line
- when /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/
- return Version.new($1, "#{$2 == "(none)" ? "0" : $2}:#{$3}-#{$4}", $5)
+ # this will resolve things like `/usr/bin/perl` or virtual packages like `mysql` -- it will not work (well? at all?) with globs that match multiple packages
+ def resolved_package_lock_names(names)
+ names.each_with_index.map do |name, i|
+ unless name.nil?
+ if installed_version(i).version.nil?
+ available_version(i).name
+ else
+ installed_version(i).name
+ end
end
end
end
+ def locked_packages
+ @locked_packages ||=
+ begin
+ locked = dnf("versionlock", "list")
+ locked.stdout.each_line.map do |line|
+ line.sub(/-[^-]*-[^-]*$/, "").split(":").last.strip
+ end
+ end
+ end
+
+ def packages_all_locked?(names, versions)
+ resolved_package_lock_names(names).all? { |n| locked_packages.include? n }
+ end
+
+ def packages_all_unlocked?(names, versions)
+ !resolved_package_lock_names(names).any? { |n| locked_packages.include? n }
+ end
+
+ def version_gt?(v1, v2)
+ return false if v1.nil? || v2.nil?
+
+ python_helper.compare_versions(v1, v2) == 1
+ end
+
+ def version_equals?(v1, v2)
+ return false if v1.nil? || v2.nil?
+
+ python_helper.compare_versions(v1, v2) == 0
+ end
+
def version_compare(v1, v2)
python_helper.compare_versions(v1, v2)
end
+ def resolve_source_to_version_obj
+ shell_out!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n' #{new_resource.source}").stdout.each_line do |line|
+ # this is another case of committing the sin of doing some lightweight mangling of RPM versions in ruby -- but the output of the rpm command
+ # does not match what the yum library accepts.
+ 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
+
# @return Array<Version>
def available_version(index)
@available_version ||= []
@@ -142,7 +198,7 @@ class Chef
@available_version[index] ||= if new_resource.source
resolve_source_to_version_obj
else
- python_helper.query(:whatavailable, package_name_array[index], safe_version_array[index], safe_arch_array[index])
+ python_helper.package_query(:whatavailable, package_name_array[index], version: safe_version_array[index], arch: safe_arch_array[index], options: options)
end
@available_version[index]
@@ -152,9 +208,9 @@ class Chef
def installed_version(index)
@installed_version ||= []
@installed_version[index] ||= if new_resource.source
- python_helper.query(:whatinstalled, available_version(index).name, safe_version_array[index], safe_arch_array[index])
+ python_helper.package_query(:whatinstalled, available_version(index).name, arch: safe_arch_array[index], options: options)
else
- python_helper.query(:whatinstalled, package_name_array[index], safe_version_array[index], safe_arch_array[index])
+ python_helper.package_query(:whatinstalled, package_name_array[index], arch: safe_arch_array[index], options: options)
end
@installed_version[index]
end
diff --git a/lib/chef/provider/package/dnf/dnf_helper.py b/lib/chef/provider/package/dnf/dnf_helper.py
index 4ec343efac..f4c031dec0 100644
--- a/lib/chef/provider/package/dnf/dnf_helper.py
+++ b/lib/chef/provider/package/dnf/dnf_helper.py
@@ -26,6 +26,17 @@ def get_sack():
except AttributeError:
pass
base.read_all_repos()
+ repos = base.repos
+
+ if 'repos' in command:
+ for repo_pattern in command['repos']:
+ if 'enable' in repo_pattern:
+ for repo in repos.get_matching(repo_pattern['enable']):
+ repo.enable()
+ if 'disable' in repo_pattern:
+ for repo in repos.get_matching(repo_pattern['disable']):
+ repo.disable()
+
try:
base.configure_plugins()
except AttributeError:
@@ -41,13 +52,38 @@ def flushcache():
pass
get_sack().load_system_repo(build_cache=True)
+def version_tuple(versionstr):
+ e = '0'
+ v = None
+ r = None
+ colon_index = versionstr.find(':')
+ if colon_index > 0:
+ e = str(versionstr[:colon_index])
+ dash_index = versionstr.find('-')
+ if dash_index > 0:
+ tmp = versionstr[colon_index + 1:dash_index]
+ if tmp != '':
+ v = tmp
+ arch_index = versionstr.find('.', dash_index)
+ if arch_index > 0:
+ r = versionstr[dash_index + 1:arch_index]
+ else:
+ r = versionstr[dash_index + 1:]
+ else:
+ tmp = versionstr[colon_index + 1:]
+ if tmp != '':
+ v = tmp
+ return (e, v, r)
+
def versioncompare(versions):
sack = get_sack()
if (versions[0] is None) or (versions[1] is None):
- sys.stdout.write('0\n')
+ outpipe.write('0\n')
+ outpipe.flush()
else:
- evr_comparison = sack.evr_cmp(versions[0], versions[1])
- sys.stdout.write('{}\n'.format(evr_comparison))
+ evr_comparison = dnf.rpm.rpm.labelCompare(version_tuple(versions[0]), version_tuple(versions[1]))
+ outpipe.write('{}\n'.format(evr_comparison))
+ outpipe.flush()
def query(command):
sack = get_sack()
@@ -79,37 +115,59 @@ def query(command):
pkgs = q.latest(1).run()
if not pkgs:
- sys.stdout.write('{} nil nil\n'.format(command['provides'].split().pop(0)))
+ outpipe.write('{} nil nil\n'.format(command['provides'].split().pop(0)))
+ outpipe.flush()
else:
# make sure we picked the package with the highest version
pkgs.sort
pkg = pkgs.pop()
- sys.stdout.write('{} {}:{}-{} {}\n'.format(pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch))
+ outpipe.write('{} {}:{}-{} {}\n'.format(pkg.name, pkg.epoch, pkg.version, pkg.release, pkg.arch))
+ outpipe.flush()
# the design of this helper is that it should try to be 'brittle' and fail hard and exit in order
# to keep process tables clean. additional error handling should probably be added to the retry loop
# on the ruby side.
def exit_handler(signal, frame):
+ if base is not None:
+ base.close()
sys.exit(0)
-signal.signal(signal.SIGINT, exit_handler)
-signal.signal(signal.SIGHUP, exit_handler)
-signal.signal(signal.SIGPIPE, exit_handler)
-
-while 1:
- # kill self if we get orphaned (tragic)
- ppid = os.getppid()
- if ppid == 1:
- sys.exit(0)
- line = sys.stdin.readline()
- command = json.loads(line)
- if command['action'] == "whatinstalled":
- query(command)
- elif command['action'] == "whatavailable":
- query(command)
- elif command['action'] == "flushcache":
- flushcache()
- elif command['action'] == "versioncompare":
- versioncompare(command['versions'])
- else:
- raise RuntimeError("bad command")
+def setup_exit_handler():
+ signal.signal(signal.SIGINT, exit_handler)
+ signal.signal(signal.SIGHUP, exit_handler)
+ signal.signal(signal.SIGPIPE, exit_handler)
+ signal.signal(signal.SIGQUIT, exit_handler)
+
+if len(sys.argv) < 3:
+ inpipe = sys.stdin
+ outpipe = sys.stdout
+else:
+ inpipe = os.fdopen(int(sys.argv[1]), "r")
+ outpipe = os.fdopen(int(sys.argv[2]), "w")
+
+try:
+ while 1:
+ # kill self if we get orphaned (tragic)
+ ppid = os.getppid()
+ if ppid == 1:
+ raise RuntimeError("orphaned")
+
+ setup_exit_handler()
+ line = inpipe.readline()
+
+ try:
+ command = json.loads(line)
+ except ValueError:
+ raise RuntimeError("bad json parse")
+
+ if command['action'] == "whatinstalled":
+ query(command)
+ elif command['action'] == "whatavailable":
+ query(command)
+ elif command['action'] == "versioncompare":
+ versioncompare(command['versions'])
+ else:
+ raise RuntimeError("bad command")
+finally:
+ if base is not None:
+ base.closeRpmDB()
diff --git a/lib/chef/provider/package/dnf/python_helper.rb b/lib/chef/provider/package/dnf/python_helper.rb
index 176ed55d3d..c591571a69 100644
--- a/lib/chef/provider/package/dnf/python_helper.rb
+++ b/lib/chef/provider/package/dnf/python_helper.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016-2017, Chef Software Inc.
+# Copyright:: Copyright 2016-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +18,7 @@
require_relative "../../../mixin/which"
require_relative "../../../mixin/shell_out"
require_relative "version"
+require "singleton" unless defined?(Singleton)
require "timeout" unless defined?(Timeout)
class Chef
@@ -32,6 +33,8 @@ class Chef
attr_accessor :stdin
attr_accessor :stdout
attr_accessor :stderr
+ attr_accessor :inpipe
+ attr_accessor :outpipe
attr_accessor :wait_thr
DNF_HELPER = ::File.expand_path(::File.join(::File.dirname(__FILE__), "dnf_helper.py")).freeze
@@ -50,16 +53,28 @@ class Chef
def start
ENV["PYTHONUNBUFFERED"] = "1"
- @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(dnf_command)
+ @inpipe, inpipe_write = IO.pipe
+ outpipe_read, @outpipe = IO.pipe
+ @stdin, @stdout, @stderr, @wait_thr = Open3.popen3("#{dnf_command} #{outpipe_read.fileno} #{inpipe_write.fileno}", outpipe_read.fileno => outpipe_read, inpipe_write.fileno => inpipe_write, close_others: false)
+ outpipe_read.close
+ inpipe_write.close
end
def reap
unless wait_thr.nil?
- Process.kill("KILL", wait_thr.pid) rescue nil
+ Process.kill("INT", wait_thr.pid) rescue nil
+ begin
+ Timeout.timeout(3) do
+ wait_thr.value # this calls waitpid()
+ end
+ rescue Timeout::Error
+ Process.kill("KILL", wait_thr.pid) rescue nil
+ end
stdin.close unless stdin.nil?
stdout.close unless stdout.nil?
stderr.close unless stderr.nil?
- wait_thr.value # this calls waitpit()
+ inpipe.close unless inpipe.nil?
+ outpipe.close unless outpipe.nil?
end
end
@@ -68,26 +83,39 @@ class Chef
end
def compare_versions(version1, version2)
- with_helper do
- json = build_version_query("versioncompare", [version1, version2])
- Chef::Log.trace "sending '#{json}' to python helper"
- stdin.syswrite json + "\n"
- stdout.sysread(4096).chomp.to_i
+ query("versioncompare", { "versions" => [version1, version2] }).to_i
+ end
+
+ def options_params(options)
+ options.each_with_object({}) do |opt, h|
+ if opt =~ /--enablerepo=(.+)/
+ $1.split(",").each do |repo|
+ h["repos"] ||= []
+ h["repos"].push( { "enable" => repo } )
+ end
+ end
+ if opt =~ /--disablerepo=(.+)/
+ $1.split(",").each do |repo|
+ h["repos"] ||= []
+ h["repos"].push( { "disable" => repo } )
+ end
+ end
end
end
# @return Array<Version>
- def query(action, provides, version = nil, arch = nil)
- with_helper do
- json = build_query(action, provides, version, arch)
- Chef::Log.trace "sending '#{json}' to python helper"
- stdin.syswrite json + "\n"
- output = stdout.sysread(4096).chomp
- Chef::Log.trace "got '#{output}' from python helper"
- version = parse_response(output)
- Chef::Log.trace "parsed #{version} from python helper"
- version
- end
+ # NB: "options" here is the dnf_package options hash and is deliberately not **opts
+ def package_query(action, provides, version: nil, arch: nil, options: {})
+ parameters = { "provides" => provides, "version" => version, "arch" => arch }
+ repo_opts = options_params(options || {})
+ parameters.merge!(repo_opts)
+ # XXX: for now we restart before and after every query with an enablerepo/disablerepo to clean the helpers internal state
+ restart unless repo_opts.empty?
+ query_output = query(action, parameters)
+ version = parse_response(query_output.lines.last)
+ Chef::Log.trace "parsed #{version} from python helper"
+ restart unless repo_opts.empty?
+ version
end
def restart
@@ -116,17 +144,28 @@ class Chef
hash["version"] = version
end
- def build_query(action, provides, version, arch)
- hash = { "action" => action }
- hash["provides"] = provides
- add_version(hash, version) unless version.nil?
- hash["arch" ] = arch unless arch.nil?
- FFI_Yajl::Encoder.encode(hash)
+ def query(action, parameters)
+ with_helper do
+ json = build_query(action, parameters)
+ Chef::Log.trace "sending '#{json}' to python helper"
+ outpipe.syswrite json + "\n"
+ output = inpipe.sysread(4096).chomp
+ Chef::Log.trace "got '#{output}' from python helper"
+ return output
+ end
end
- def build_version_query(action, versions)
+ def build_query(action, parameters)
hash = { "action" => action }
- hash["versions"] = versions
+ parameters.each do |param_name, param_value|
+ hash[param_name] = param_value unless param_value.nil?
+ end
+
+ # Special handling for certain action / param combos
+ if %i{whatinstalled whatavailable}.include?(action)
+ add_version(hash, parameters["version"]) unless parameters["version"].nil?
+ end
+
FFI_Yajl::Encoder.encode(hash)
end
@@ -135,12 +174,16 @@ class Chef
array.each_slice(3).map { |x| Version.new(*x) }.first
end
- def drain_stderr
+ def drain_fds
output = ""
- output += stderr.sysread(4096).chomp until IO.select([stderr], nil, nil, 0).nil?
+ fds, = IO.select([stderr, stdout, inpipe], nil, nil, 0)
+ unless fds.nil?
+ fds.each do |fd|
+ output += fd.sysread(4096) rescue ""
+ end
+ end
output
- rescue
- # we must rescue EOFError, and we don't much care about errors on stderr anyway
+ rescue => e
output
end
@@ -151,23 +194,23 @@ class Chef
check
ret = yield
end
- output = drain_stderr
+ output = drain_fds
unless output.empty?
- Chef::Log.trace "discarding output on stderr from python helper: #{output}"
+ Chef::Log.trace "discarding output on stderr/stdout from python helper: #{output}"
end
ret
rescue EOFError, Errno::EPIPE, Timeout::Error, Errno::ESRCH => e
- output = drain_stderr
+ output = drain_fds
if ( max_retries -= 1 ) > 0
unless output.empty?
- Chef::Log.trace "discarding output on stderr from python helper: #{output}"
+ Chef::Log.trace "discarding output on stderr/stdout from python helper: #{output}"
end
restart
retry
else
raise e if output.empty?
- raise "dnf-helper.py had stderr output:\n\n#{output}"
+ raise "dnf-helper.py had stderr/stdout output:\n\n#{output}"
end
end
end
diff --git a/lib/chef/provider/package/dnf/version.rb b/lib/chef/provider/package/dnf/version.rb
index 3cff5b0437..5fe3a76e3e 100644
--- a/lib/chef/provider/package/dnf/version.rb
+++ b/lib/chef/provider/package/dnf/version.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016, Chef Software, Inc.
+# Copyright:: Copyright 2016-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,13 +33,17 @@ class Chef
end
def to_s
- "#{name}-#{version}.#{arch}"
+ "#{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
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index ca24ea2f5b..3251f4e236 100644
--- a/lib/chef/provider/package/yum.rb
+++ b/lib/chef/provider/package/yum.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016-2018, Chef Software Inc.
+# Copyright:: Copyright 2016-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -202,14 +202,6 @@ class Chef
python_helper.compare_versions(v1, v2)
end
- # Generate the yum syntax for the package
- def yum_syntax(name, version, arch)
- s = name
- s += "-#{version}" if version
- s += ".#{arch}" if arch
- s
- end
-
def resolve_source_to_version_obj
shell_out!("rpm -qp --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n' #{new_resource.source}").stdout.each_line do |line|
# this is another case of committing the sin of doing some lightweight mangling of RPM versions in ruby -- but the output of the rpm command
diff --git a/lib/chef/provider/package/yum/python_helper.rb b/lib/chef/provider/package/yum/python_helper.rb
index 19c0b0a474..2080fed6ff 100644
--- a/lib/chef/provider/package/yum/python_helper.rb
+++ b/lib/chef/provider/package/yum/python_helper.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016-2018, Chef Software Inc.
+# Copyright:: Copyright 2016-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/spec/functional/resource/dnf_package_spec.rb b/spec/functional/resource/dnf_package_spec.rb
index 0e7009f003..ec167238f7 100644
--- a/spec/functional/resource/dnf_package_spec.rb
+++ b/spec/functional/resource/dnf_package_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016-2019, Chef Software Inc.
+# Copyright:: Copyright 2016-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,9 +21,13 @@ require "chef/mixin/shell_out"
# run this test only for following platforms.
exclude_test = !(%w{rhel fedora amazon}.include?(ohai[:platform_family]) && File.exist?("/usr/bin/dnf"))
-describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
+describe Chef::Resource::DnfPackage, :requires_root, external: exclude_test do
include Chef::Mixin::ShellOut
+ # NOTE: every single test here either needs to explicitly call flush_cache or needs to explicitly
+ # call preinstall (which explicitly calls flush_cache). It is your responsibility to do one or the
+ # other in order to minimize calling flush_cache a half dozen times per test.
+
def flush_cache
# needed on at least fc23/fc24 sometimes to deal with the dnf cache getting out of sync with the rpm db
FileUtils.rm_f "/var/cache/dnf/@System.solv"
@@ -37,6 +41,10 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
flush_cache
end
+ before(:all) do
+ shell_out!("dnf -y install dnf-plugins-core")
+ end
+
before(:each) do
File.open("/etc/yum.repos.d/chef-dnf-localtesting.repo", "w+") do |f|
f.write <<~EOF
@@ -47,17 +55,24 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
gpgcheck=0
EOF
end
- shell_out!("rpm -qa | grep chef_rpm | xargs -r rpm -e")
+ shell_out!("rpm -qa --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | grep chef_rpm | xargs -r rpm -e")
+ # next line is useful cleanup if you happen to have been testing both yum + dnf func tests on the same box and
+ # have some yum garbage left around
+ FileUtils.rm_f "/etc/yum.repos.d/chef-yum-localtesting.repo"
end
after(:all) do
- shell_out!("rpm -qa | grep chef_rpm | xargs -r rpm -e")
+ shell_out!("rpm -qa --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | grep chef_rpm | xargs -r rpm -e")
FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
end
let(:package_name) { "chef_rpm" }
let(:dnf_package) { Chef::Resource::DnfPackage.new(package_name, run_context) }
+ def pkg_arch
+ ohai[:kernel][:machine]
+ end
+
describe ":install" do
context "vanilla use case" do
let(:package_name) { "chef_rpm" }
@@ -66,47 +81,47 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
flush_cache
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "does not install if the package is installed" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "does not install twice" do
flush_cache
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "does not install if the prior version package is installed" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
- it "does not install if the i686 package is installed" do
- skip "FIXME: do nothing, or install the x86_64 version?"
+ it "does not install if the i686 package is installed", :intel_64bit do
+ skip "FIXME: do nothing, or install the #{pkg_arch} version?"
preinstall("chef_rpm-1.10-1.i686.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.i686")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.i686$")
end
- it "does not install if the prior version i686 package is installed" do
- skip "FIXME: do nothing, or install the x86_64 version?"
+ it "does not install if the prior version i686 package is installed", :intel_64bit do
+ skip "FIXME: do nothing, or install the #{pkg_arch} version?"
preinstall("chef_rpm-1.2-1.i686.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.i686")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.i686$")
end
end
@@ -116,7 +131,7 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rpm-1.10")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "works with an older version" do
@@ -124,15 +139,23 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rpm-1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "works with an evra" do
+ flush_cache
+ dnf_package.package_name("chef_rpm-0:1.2-1.#{pkg_arch}")
+ dnf_package.run_action(:install)
+ expect(dnf_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.2-1.#{pkg_arch}$")
end
- it "works with an evr" do
+ it "works with version and release" do
flush_cache
- dnf_package.package_name("chef_rpm-0:1.2-1")
+ dnf_package.package_name("chef_rpm-1.2-1")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "works with a version glob" do
@@ -140,7 +163,7 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rpm-1*")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "works with a name glob + version glob" do
@@ -148,7 +171,23 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rp*-1*")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "upgrades when the installed version does not match the version string" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm-1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_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 "downgrades when the installed version is higher than the package_name version" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm-1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_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.2-1.#{pkg_arch}$")
end
end
@@ -160,7 +199,7 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.version("1.10")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "matches with a glob" do
@@ -169,7 +208,7 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.version("1*")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "matches the vr" do
@@ -178,7 +217,7 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.version("1.10-1")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "matches the evr" do
@@ -187,58 +226,47 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.version("0:1.10-1")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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
- # only works on rhel >= 8, was broken on old dnf
it "matches with a vr glob", :rhel_gte_8 do
flush_cache
dnf_package.package_name("chef_rpm")
dnf_package.version("1.10-1*")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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
- # only works on rhel >= 8, was broken on old dnf
it "matches with an evr glob", :rhel_gte_8 do
flush_cache
dnf_package.package_name("chef_rpm")
dnf_package.version("0:1.10-1*")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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
end
context "downgrades" do
- it "just work with DNF" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
- dnf_package.version("1.2")
- dnf_package.run_action(:install)
- expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
- end
-
- it "throws a deprecation warning with allow_downgrade" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- expect(Chef).to receive(:deprecated).with(:dnf_package_allow_downgrade, /^the allow_downgrade property on the dnf_package provider is not used/)
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
- dnf_package.version("1.2")
+ it "downgrades the package when allow_downgrade" do
+ flush_cache
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm")
+ dnf_package.version("1.2-1")
dnf_package.run_action(:install)
- dnf_package.allow_downgrade true
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
end
- context "with arches" do
+ context "with arches", :intel_64bit do
it "installs with 64-bit arch in the name" do
flush_cache
- dnf_package.package_name("chef_rpm.x86_64")
+ dnf_package.package_name("chef_rpm.#{pkg_arch}")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "installs with 32-bit arch in the name" do
@@ -246,16 +274,16 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rpm.i686")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.i686")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.i686$")
end
it "installs with 64-bit arch in the property" do
flush_cache
dnf_package.package_name("chef_rpm")
- dnf_package.arch("x86_64")
+ dnf_package.arch((pkg_arch).to_s)
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "installs with 32-bit arch in the property" do
@@ -264,7 +292,7 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.arch("i686")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.i686")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.i686$")
end
end
@@ -274,23 +302,23 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rpm >= 1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "when it is met, it does nothing" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.package_name("chef_rpm >= 1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "when it is met, it does nothing" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.package_name("chef_rpm >= 1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "with nothing intalled, it installs the latest version" do
@@ -298,23 +326,39 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
dnf_package.package_name("chef_rpm > 1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "when it is not met by an installed rpm, it upgrades" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.package_name("chef_rpm > 1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "with an equality constraint, when it is not met by an installed rpm, it upgrades" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm = 1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_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 "with an equality constraint, when it is met by an installed rpm, it does nothing" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm = 1.2")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "when it is met by an installed rpm, it does nothing" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.package_name("chef_rpm > 1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "when there is no solution to the contraint" do
@@ -324,10 +368,34 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
end
it "when there is no solution to the contraint but an rpm is preinstalled" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.package_name("chef_rpm > 2.0")
expect { dnf_package.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /No candidate version available/)
end
+
+ it "with a less than constraint, when nothing is installed, it installs" do
+ flush_cache
+ dnf_package.package_name("chef_rpm < 1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_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.2-1.#{pkg_arch}$")
+ end
+
+ it "with a less than constraint, when the install version matches, it does nothing" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm < 1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "with a less than constraint, when the install version fails, it should downgrade" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm < 1.10")
+ dnf_package.run_action(:install)
+ expect(dnf_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.2-1.#{pkg_arch}$")
+ end
end
context "with source arguments" do
@@ -349,163 +417,237 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
flush_cache
dnf_package.name "something"
dnf_package.package_name "somethingelse"
- dnf_package.source("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ dnf_package.source("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "installs the package when the name is a path to a file" do
flush_cache
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "downgrade on a local file with allow_downgrade true works" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.version "1.2-1"
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_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.2-1.#{pkg_arch}$")
end
it "does not downgrade the package with :install" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "does not upgrade the package with :install" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "is idempotent when the package is already installed" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "is idempotent when the package is already installed and there is a version string" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.version "1.2-1"
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "is idempotent when the package is already installed and there is a version string with arch" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.version "1.2-1.#{pkg_arch}"
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.run_action(:install)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
end
context "with no available version" do
it "works when a package is installed" do
FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "works with a local source" do
FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
flush_cache
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
end
- context "multipackage with arches" do
+ context "multipackage with arches", :intel_64bit do
it "installs two rpms" do
flush_cache
- dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.package_name([ "chef_rpm.#{pkg_arch}", "chef_rpm.i686" ] )
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.x86_64/)
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.i686/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.#{pkg_arch}$/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.i686$/)
end
it "does nothing if both are installed" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm", "chef_rpm-1.10-1.i686.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm", "chef_rpm-1.10-1.i686.rpm")
flush_cache
- dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.package_name([ "chef_rpm.#{pkg_arch}", "chef_rpm.i686" ] )
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
end
it "installs the second rpm if the first is installed" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
- dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name([ "chef_rpm.#{pkg_arch}", "chef_rpm.i686" ] )
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.x86_64/)
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.i686/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.#{pkg_arch}$/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.i686$/)
end
it "installs the first rpm if the second is installed" do
preinstall("chef_rpm-1.10-1.i686.rpm")
- dnf_package.package_name([ "chef_rpm.x86_64", "chef_rpm.i686" ] )
+ dnf_package.package_name([ "chef_rpm.#{pkg_arch}", "chef_rpm.i686" ] )
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.x86_64/)
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.i686/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.#{pkg_arch}$/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.i686$/)
end
# unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
it "installs two rpms with multi-arch" do
flush_cache
dnf_package.package_name(%w{chef_rpm chef_rpm} )
- dnf_package.arch(%w{x86_64 i686})
+ dnf_package.arch([pkg_arch, "i686"])
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.x86_64/)
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.i686/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.#{pkg_arch}$/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.i686$/)
end
# unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
it "installs the second rpm if the first is installed (muti-arch)" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.package_name(%w{chef_rpm chef_rpm} )
- dnf_package.arch(%w{x86_64 i686})
+ dnf_package.arch([pkg_arch, "i686"])
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.x86_64/)
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.i686/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.#{pkg_arch}$/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.i686$/)
end
# unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
it "installs the first rpm if the second is installed (muti-arch)" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.package_name(%w{chef_rpm chef_rpm} )
- dnf_package.arch(%w{x86_64 i686})
+ dnf_package.arch([pkg_arch, "i686"])
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.x86_64/)
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match(/chef_rpm-1.10-1.i686/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.#{pkg_arch}$/)
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match(/^chef_rpm-1.10-1.i686$/)
end
# unlikely to work consistently correct, okay to deprecate the arch-array in favor of the arch in the name
it "does nothing if both are installed (muti-arch)" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm", "chef_rpm-1.10-1.i686.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm", "chef_rpm-1.10-1.i686.rpm")
dnf_package.package_name(%w{chef_rpm chef_rpm} )
- dnf_package.arch(%w{x86_64 i686})
+ dnf_package.arch([pkg_arch, "i686"])
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be false
end
end
+
+ context "repo controls" do
+ it "should fail with the repo disabled" do
+ flush_cache
+ dnf_package.options("--disablerepo=chef-dnf-localtesting")
+ expect { dnf_package.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /No candidate version available/)
+ end
+
+ it "should work with disablerepo first" do
+ flush_cache
+ dnf_package.options(["--disablerepo=*", "--enablerepo=chef-dnf-localtesting"])
+ dnf_package.run_action(:install)
+ expect(dnf_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 "should work to enable a disabled repo" do
+ shell_out!("dnf config-manager --set-disabled chef-dnf-localtesting")
+ flush_cache
+ expect { dnf_package.run_action(:install) }.to raise_error(Chef::Exceptions::Package, /No candidate version available/)
+ flush_cache
+ dnf_package.options("--enablerepo=chef-dnf-localtesting")
+ dnf_package.run_action(:install)
+ expect(dnf_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 "when an idempotent install action is run, does not leave repos disabled" do
+ flush_cache
+ # this is a bit tricky -- we need this action to be idempotent, so that it doesn't recycle any
+ # caches, but need it to hit whatavailable with the repo disabled. using :upgrade like this
+ # accomplishes both those goals (it would be easier if we had other rpms in this repo, but with
+ # one rpm we neeed to do this).
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.options("--disablerepo=chef-dnf-localtesting")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ # now we're still using the same cache in the dnf_helper.py cache and we test to see if the
+ # repo that we temporarily disabled is enabled on this pass.
+ dnf_package.package_name("chef_rpm-1.10-1.#{pkg_arch}")
+ dnf_package.options(nil)
+ dnf_package.run_action(:install)
+ expect(dnf_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
+ end
end
describe ":upgrade" do
context "downgrades" do
it "just work with DNF" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.version("1.2")
dnf_package.run_action(:install)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}")
end
it "throws a deprecation warning with allow_downgrade" do
Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect(Chef).to receive(:deprecated).with(:dnf_package_allow_downgrade, /^the allow_downgrade property on the dnf_package provider is not used/)
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.version("1.2")
dnf_package.run_action(:install)
dnf_package.allow_downgrade true
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}")
end
end
@@ -514,62 +656,144 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
flush_cache
dnf_package.name "something"
dnf_package.package_name "somethingelse"
- dnf_package.source("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ dnf_package.source("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "installs the package when the name is a path to a file" do
flush_cache
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
- it "downgrades the package" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ it "downgrades the package when allow_downgrade is true" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "upgrades the package" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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 "is idempotent when the package is already installed" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
end
context "with no available version" do
it "works when a package is installed" do
FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
end
it "works with a local source" do
FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
flush_cache
- dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.x86_64.rpm")
+ dnf_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:upgrade)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.x86_64")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+ end
+
+ context "version pinning" do
+ it "with an equality pin in the name it upgrades a prior package" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm-1.10")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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 "with a prco equality pin in the name it upgrades a prior package" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm == 1.10")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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 "with an equality pin in the name it downgrades a later package" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm-1.2")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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.2-1.#{pkg_arch}$")
+ end
+
+ it "with a prco equality pin in the name it downgrades a later package" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm == 1.2")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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.2-1.#{pkg_arch}$")
+ end
+
+ it "with a > pin in the name and no rpm installed it installs" do
+ flush_cache
+ dnf_package.package_name("chef_rpm > 1.2")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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 "with a < pin in the name and no rpm installed it installs" do
+ flush_cache
+ dnf_package.package_name("chef_rpm < 1.10")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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.2-1.#{pkg_arch}$")
+ end
+
+ it "with a > pin in the name and matching rpm installed it does nothing" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm > 1.2")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be false
+ 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 "with a < pin in the name and no rpm installed it installs" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm < 1.10")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$")
+ end
+
+ it "with a > pin in the name and non-matching rpm installed it upgrades" do
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm > 1.2")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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 "with a < pin in the name and non-matching rpm installed it downgrades" do
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
+ dnf_package.package_name("chef_rpm < 1.10")
+ dnf_package.run_action(:upgrade)
+ expect(dnf_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.2-1.#{pkg_arch}$")
end
end
end
@@ -581,106 +805,167 @@ describe Chef::Resource::RpmPackage, :requires_root, external: exclude_test do
flush_cache
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
it "removes the package if the package is installed" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
it "does not remove the package twice" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
it "removes the package if the prior version package is installed" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
- it "removes the package if the i686 package is installed" do
+ it "removes the package if the i686 package is installed", :intel_64bit do
skip "FIXME: should this be fixed or is the current behavior correct?"
preinstall("chef_rpm-1.10-1.i686.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
- it "removes the package if the prior version i686 package is installed" do
+ it "removes the package if the prior version i686 package is installed", :intel_64bit do
skip "FIXME: should this be fixed or is the current behavior correct?"
preinstall("chef_rpm-1.2-1.i686.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
end
- context "with 64-bit arch" do
- let(:package_name) { "chef_rpm.x86_64" }
+ context "with 64-bit arch", :intel_64bit do
+ let(:package_name) { "chef_rpm.#{pkg_arch}" }
it "does nothing if the package is not installed" do
flush_cache
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
it "removes the package if the package is installed" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
it "removes the package if the prior version package is installed" do
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
it "does nothing if the i686 package is installed" do
preinstall("chef_rpm-1.10-1.i686.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.i686")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.i686$")
end
it "does nothing if the prior version i686 package is installed" do
preinstall("chef_rpm-1.2-1.i686.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be false
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.2-1.i686")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.i686$")
end
end
- context "with 32-bit arch" do
+ context "with 32-bit arch", :intel_64bit do
let(:package_name) { "chef_rpm.i686" }
it "removes only the 32-bit arch if both are installed" do
- preinstall("chef_rpm-1.10-1.x86_64.rpm", "chef_rpm-1.10-1.i686.rpm")
+ preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm", "chef_rpm-1.10-1.i686.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("chef_rpm-1.10-1.x86_64")
+ 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
end
context "with no available version" do
it "works when a package is installed" do
FileUtils.rm_f "/etc/yum.repos.d/chef-dnf-localtesting.repo"
- preinstall("chef_rpm-1.2-1.x86_64.rpm")
+ preinstall("chef_rpm-1.2-1.#{pkg_arch}.rpm")
dnf_package.run_action(:remove)
expect(dnf_package.updated_by_last_action?).to be true
- expect(shell_out("rpm -q chef_rpm").stdout.chomp).to eql("package chef_rpm is not installed")
+ expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^package chef_rpm is not installed$")
end
end
end
+
+ describe ":lock and :unlock" do
+ before(:all) do
+ shell_out("dnf -y install python3-dnf-plugin-versionlock")
+ end
+
+ before(:each) do
+ shell_out("dnf versionlock delete 'chef_rpm-*'") # will exit with error when nothing is locked, we don't care
+ end
+
+ it "locks an rpm" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.run_action(:lock)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("dnf versionlock list").stdout.chomp).to match("^chef_rpm-0:")
+ end
+
+ it "does not lock if its already locked" do
+ flush_cache
+ shell_out!("dnf versionlock add chef_rpm")
+ dnf_package.package_name("chef_rpm")
+ dnf_package.run_action(:lock)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("dnf versionlock list").stdout.chomp).to match("^chef_rpm-0:")
+ end
+
+ it "unlocks an rpm" do
+ flush_cache
+ shell_out!("dnf versionlock add chef_rpm")
+ dnf_package.package_name("chef_rpm")
+ dnf_package.run_action(:unlock)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("dnf versionlock list").stdout.chomp).not_to match("^chef_rpm-0:")
+ end
+
+ it "does not unlock an already locked rpm" do
+ flush_cache
+ dnf_package.package_name("chef_rpm")
+ dnf_package.run_action(:unlock)
+ expect(dnf_package.updated_by_last_action?).to be false
+ expect(shell_out("dnf versionlock list").stdout.chomp).not_to match("^chef_rpm-0:")
+ end
+
+ it "check that we can lock based on provides" do
+ flush_cache
+ dnf_package.package_name("chef_rpm_provides")
+ dnf_package.run_action(:lock)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("dnf versionlock list").stdout.chomp).to match("^chef_rpm-0:")
+ end
+
+ it "check that we can unlock based on provides" do
+ flush_cache
+ shell_out!("dnf versionlock add chef_rpm")
+ dnf_package.package_name("chef_rpm_provides")
+ dnf_package.run_action(:unlock)
+ expect(dnf_package.updated_by_last_action?).to be true
+ expect(shell_out("dnf versionlock list").stdout.chomp).not_to match("^chef_rpm-0:")
+ end
+ end
end
diff --git a/spec/unit/provider/package/dnf/python_helper_spec.rb b/spec/unit/provider/package/dnf/python_helper_spec.rb
index 505217bf90..a7873bf1f8 100644
--- a/spec/unit/provider/package/dnf/python_helper_spec.rb
+++ b/spec/unit/provider/package/dnf/python_helper_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2017-2017, Chef Software Inc.
+# Copyright:: Copyright 2017-2020, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,6 +24,6 @@ describe Chef::Provider::Package::Dnf::PythonHelper do
it "propagates stacktraces on stderr from the forked subprocess" do
allow(helper).to receive(:dnf_command).and_return("ruby -e 'raise \"your hands in the air\"'")
- expect { helper.query(:whatprovides, "tcpdump") }.to raise_error(/your hands in the air/)
+ expect { helper.package_query(:whatprovides, "tcpdump") }.to raise_error(/your hands in the air/)
end
end