|
|
|
# Tests for skip_broken and allowerasing
|
|
|
|
# (and a bit of nobest because the test case is too good to pass up)
|
|
|
|
#
|
|
|
|
# There are a lot of fairly complex, corner cases we test here especially towards the end.
|
|
|
|
#
|
|
|
|
# The test repo is generated from the "skip-broken" repo in this repository:
|
|
|
|
# https://github.com/relrod/ansible-ci-contrived-yum-repos
|
|
|
|
#
|
|
|
|
# It is laid out like this:
|
|
|
|
#
|
|
|
|
# There are three packages, `broken-a`, `broken-b`, `broken-c`.
|
|
|
|
#
|
|
|
|
# * broken-a has three versions: 1.2.3, 1.2.3.4, 1.2.4, 2.0.0.
|
|
|
|
# * 1.2.3 and 1.2.4 have no dependencies
|
|
|
|
# * 1.2.3.4 and 2.0.0 both depend on a non-existent package (to break depsolving)
|
|
|
|
#
|
|
|
|
# * broken-b depends on broken-a-1.2.3
|
|
|
|
# * broken-c depends on broken-a-1.2.4
|
|
|
|
# * broken-d depends on broken-a (no version constraint)
|
|
|
|
#
|
|
|
|
# This allows us to test various upgrades, downgrades, and installs with broken dependencies.
|
|
|
|
# skip_broken should usually be successful in the upgrade/downgrade case, it will just do nothing.
|
|
|
|
#
|
|
|
|
# There is a nobest testcase or two thrown in, simply because this organization provides a very
|
|
|
|
# good test case for that behavior as well. For example, just installing "broken-a" with no version
|
|
|
|
# will try to install 2.0.0 which is broken. With nobest=true, it will fall back to 1.2.4. Similar
|
|
|
|
# for upgrading.
|
|
|
|
- block:
|
|
|
|
- name: Set up test yum repo
|
|
|
|
yum_repository:
|
|
|
|
name: skip-broken
|
|
|
|
description: ansible-test skip-broken test repo
|
|
|
|
baseurl: "{{ skip_broken_repo_baseurl }}"
|
|
|
|
gpgcheck: no
|
|
|
|
repo_gpgcheck: no
|
|
|
|
|
|
|
|
- name: Install two packages
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3
|
|
|
|
- broken-b
|
|
|
|
|
|
|
|
# This will fail. We have broken-a-1.2.3, and broken-b with a strong
|
|
|
|
# dependency on it. broken-c has a strong dependency on broken-a-1.2.4.
|
|
|
|
# Since installing that would break broken-b, we get a conflict.
|
|
|
|
- name: Try installing a third package, intentionally broken
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-c
|
|
|
|
ignore_errors: true
|
|
|
|
register: dnf_fail
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- dnf_fail is failed
|
|
|
|
- "'Depsolve Error' in dnf_fail.msg"
|
|
|
|
|
|
|
|
# skip_broken should still install nothing because the conflict is
|
|
|
|
# still an issue. But it should skip over the broken packages and not
|
|
|
|
# fail.
|
|
|
|
- name: Try installing it with skip_broken
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-c
|
|
|
|
skip_broken: true
|
|
|
|
register: skip_broken_res
|
|
|
|
|
|
|
|
- name: Assert that nothing got installed
|
|
|
|
assert:
|
|
|
|
that:
|
|
|
|
- skip_broken_res.msg == 'Nothing to do'
|
|
|
|
- skip_broken_res.rc == 0
|
|
|
|
- skip_broken_res.results == []
|
|
|
|
|
|
|
|
- name: Remove all test packages
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-*
|
|
|
|
state: absent
|
|
|
|
|
|
|
|
# broken-d depends on (unversioned) broken-a.
|
|
|
|
# broken-a-2.0.0 has a broken dependency that doesn't exist.
|
|
|
|
# skip_broken should cause us to skip our explicit broken-a-2.0.0
|
|
|
|
# and bring in broken-a-1.2.4 as a dep of broken-d.
|
|
|
|
- name: Ensure proper failure with explicit broken version
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-2.0.0
|
|
|
|
- broken-d
|
|
|
|
ignore_errors: true
|
|
|
|
register: dnf_fail
|
|
|
|
|
|
|
|
- name: Assert that nothing got installed
|
|
|
|
assert:
|
|
|
|
that:
|
|
|
|
- dnf_fail is failed
|
|
|
|
- "'Depsolve Error' in dnf_fail.msg"
|
|
|
|
|
|
|
|
- name: skip_broken with explicit version
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-2.0.0
|
|
|
|
- broken-d
|
|
|
|
skip_broken: true
|
|
|
|
register: skip_broken_res
|
|
|
|
|
|
|
|
- name: Assert that the right things got installed
|
|
|
|
assert:
|
|
|
|
that:
|
|
|
|
- skip_broken_res.rc == 0
|
|
|
|
- skip_broken_res.results|length == 2
|
|
|
|
- res.results|select("contains", "Installed: broken-a-1.2.4")|length > 0
|
|
|
|
- res.results|select("contains", "Installed: broken-d-1.2.5")|length > 0
|
|
|
|
|
|
|
|
- name: Remove all test packages
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-*
|
|
|
|
state: absent
|
|
|
|
|
|
|
|
# Walk the logic of _mark_package_install() here
|
|
|
|
# We need to use a full-ish NVR/wildcard. _is_newer_version_installed()
|
|
|
|
# will be false otherwise, no matter what. This might be a bug.
|
|
|
|
# Relatedly, the real "Case 1" in the code seemingly can't be reached:
|
|
|
|
# _is_newer_version_installed wants NVR, _is_installed wants name.
|
|
|
|
# Both can't be true at the same time given one pkg_spec. Thus, we start
|
|
|
|
# at "Case 2"
|
|
|
|
|
|
|
|
# prereq
|
|
|
|
- name: Install broken-a-1.2.4
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.4
|
|
|
|
state: present
|
|
|
|
|
|
|
|
# Case 2: newer version is installed, allow_downgrade is true,
|
|
|
|
# is_installed is false since we gave full NVR.
|
|
|
|
# "upgrade" to broken-a-1.2.3, allow_downgrade=true
|
|
|
|
- name: Do an "upgrade" to an older version of broken-a, allow_downgrade=true
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3-1*
|
|
|
|
state: latest
|
|
|
|
allow_downgrade: true
|
|
|
|
check_mode: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is changed
|
|
|
|
- res.results|select("contains", "Installed: broken-a-1.2.3")|length > 0
|
|
|
|
|
|
|
|
# Still case 2, but with broken package to test skip_broken
|
|
|
|
# skip_broken: false
|
|
|
|
- name: Do an "upgrade" to an older known broken version of broken-a, allow_downgrade=true, skip_broken=false
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3.4-1*
|
|
|
|
state: latest
|
|
|
|
allow_downgrade: true
|
|
|
|
check_mode: true
|
|
|
|
ignore_errors: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
# 1.2.3.4 has non-existent dep. Fail without skip_broken.
|
|
|
|
- res is failed
|
|
|
|
- "'Depsolve Error' in res.msg"
|
|
|
|
|
|
|
|
# skip_broken: true
|
|
|
|
- name: Do an "upgrade" to an older known broken version of broken-a, allow_downgrade=true, skip_broken=true
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3.4-1*
|
|
|
|
state: latest
|
|
|
|
allow_downgrade: true
|
|
|
|
skip_broken: true
|
|
|
|
check_mode: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is not changed
|
|
|
|
- res.rc == 0
|
|
|
|
- res.msg == "Nothing to do"
|
|
|
|
|
|
|
|
# Case 3: newer version installed, allow_downgrade=true, but
|
|
|
|
# upgrade=false (i.e., state: present or installed)
|
|
|
|
- name: Install an older version of broken-a than currently installed
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3-1*
|
|
|
|
state: present
|
|
|
|
allow_downgrade: true
|
|
|
|
check_mode: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is changed
|
|
|
|
- res.results|select("contains", "Installed: broken-a-1.2.3")|length > 0
|
|
|
|
|
|
|
|
# Case 3 still, with broken package and skip_broken tests like above.
|
|
|
|
- name: Install an older known broken version of broken-a, allow_downgrade=true, skip_broken=false
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3.4-1*
|
|
|
|
state: present
|
|
|
|
allow_downgrade: true
|
|
|
|
check_mode: true
|
|
|
|
ignore_errors: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
# 1.2.3.4 has non-existent dep. Fail without skip_broken.
|
|
|
|
- res is failed
|
|
|
|
- "'Depsolve Error' in res.msg"
|
|
|
|
|
|
|
|
# skip_broken: true
|
|
|
|
- name: Install an older known broken version of broken-a, allow_downgrade=true, skip_broken=true
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a-1.2.3.4-1*
|
|
|
|
state: present
|
|
|
|
allow_downgrade: true
|
|
|
|
skip_broken: true
|
|
|
|
check_mode: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is not changed
|
|
|
|
- res.rc == 0
|
|
|
|
- res.msg == "Nothing to do"
|
|
|
|
|
|
|
|
# Case 4: "upgrade" to broken-a-1.2.3, allow_downgrade=false
|
|
|
|
# is_newer_version_installed is true, allow_downgrade is false
|
|
|
|
- name: Do an "upgrade" to an older version of broken-a, allow_downgrade=false
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
#- broken-a-1.2.3-1*
|
|
|
|
- broken-a-1.2.3-1.el7.x86_64
|
|
|
|
state: latest
|
|
|
|
allow_downgrade: false
|
|
|
|
check_mode: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is not changed
|
|
|
|
- res.rc == 0
|
|
|
|
- res.msg == "Nothing to do"
|
|
|
|
|
|
|
|
# skip_broken doesn't apply to case 5 or 6 (older version installed).
|
|
|
|
# base.upgrade doesn't allow a strict= kwarg. However, nobest works here.
|
|
|
|
|
|
|
|
# Case 5: older version of package is installed, we specify name, no version
|
|
|
|
# otherwise we'd land in an earlier case. At this point, 1.2.4 is installed.
|
|
|
|
# broken-a-2.0.0 is available as an update but has a broken dependency.
|
|
|
|
- name: Update broken-a without nobest=true
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a
|
|
|
|
state: latest
|
|
|
|
best: true
|
|
|
|
ignore_errors: true
|
|
|
|
register: dnf_fail
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- dnf_fail is failed
|
|
|
|
- "'Depsolve Error' in dnf_fail.msg"
|
|
|
|
|
|
|
|
# With nobest: true, we will be "successful" but not actually perform
|
|
|
|
# any upgrade. That is, we are content not having the "best"/latest
|
|
|
|
# version.
|
|
|
|
- name: Update broken-a with nobest=true
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a
|
|
|
|
state: latest
|
|
|
|
nobest: true
|
|
|
|
register: nobest
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- nobest.rc == 0
|
|
|
|
- nobest.results == []
|
|
|
|
|
|
|
|
# Case 6: Current or older version already installed (no version specified
|
|
|
|
# in our pkg_spec) and we're requesting present, not latest.
|
|
|
|
#
|
|
|
|
# This isn't really relevant to skip_broken or nobest, but let's test it
|
|
|
|
# anyway since we're already walking the logic of the method.
|
|
|
|
- name: Install broken-a (even though it is already installed)
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-a
|
|
|
|
state: present
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is not changed
|
|
|
|
|
|
|
|
# Case 7 is already tested quite extensively above in the earlier tests.
|
|
|
|
# ######################################################################
|
|
|
|
|
|
|
|
- block:
|
|
|
|
- name: Test available package is installed while unavailable one is skipped due to skip_broken=true
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- dinginessentail
|
|
|
|
- not-in-repo
|
|
|
|
skip_broken: true
|
|
|
|
register: res
|
|
|
|
|
|
|
|
- assert:
|
|
|
|
that:
|
|
|
|
- res is changed
|
|
|
|
# There is a change in dnf5 that splits skip_broken into two options:
|
|
|
|
# skip_broken and skip_unavailable.
|
|
|
|
# TODO: for this test to pass on dnf5 the skip_unavailable option would have to be
|
|
|
|
# added to the dnf5 module and used here instead of skip_broken.
|
|
|
|
when: not dnf5|default(false)
|
|
|
|
|
|
|
|
always:
|
|
|
|
- name: Remove test yum repo
|
|
|
|
yum_repository:
|
|
|
|
name: skip-broken
|
|
|
|
state: absent
|
|
|
|
|
|
|
|
- name: Remove all test packages installed
|
|
|
|
dnf:
|
|
|
|
name:
|
|
|
|
- broken-*
|
|
|
|
- dinginessentail
|
|
|
|
state: absent
|