yum also parse obsolete package output (#45365)
* yum also parse obsolete package output This is a rebase of the patch originally proposed in https://github.com/ansible/ansible/pull/40001 by machacekondra Fixes #39978 Signed-off-by: Adam Miller <admiller@redhat.com> * properly parse the obsoletes, provide a new output entry, add changelog Signed-off-by: Adam Miller <admiller@redhat.com> * make pep8 happy Signed-off-by: Adam Miller <admiller@redhat.com> * remove q debugging output Signed-off-by: Adam Miller <admiller@redhat.com>
This commit is contained in:
parent
6c94c28a12
commit
091fb1dc3f
3 changed files with 51 additions and 19 deletions
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- "yum - when checking for updates, now properly include Obsoletes (both old and new) package data in the module JSON output, fixes https://github.com/ansible/ansible/issues/39978"
|
|
@ -1075,6 +1075,7 @@ class YumModule(YumDnf):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_check_update(check_update_output):
|
def parse_check_update(check_update_output):
|
||||||
updates = {}
|
updates = {}
|
||||||
|
obsoletes = {}
|
||||||
|
|
||||||
# remove incorrect new lines in longer columns in output from yum check-update
|
# remove incorrect new lines in longer columns in output from yum check-update
|
||||||
# yum line wrapping can move the repo to the next line
|
# yum line wrapping can move the repo to the next line
|
||||||
|
@ -1099,17 +1100,24 @@ class YumModule(YumDnf):
|
||||||
# ignore irrelevant lines
|
# ignore irrelevant lines
|
||||||
# '*' in line matches lines like mirror lists:
|
# '*' in line matches lines like mirror lists:
|
||||||
# * base: mirror.corbina.net
|
# * base: mirror.corbina.net
|
||||||
# len(line) != 3 could be junk or a continuation
|
# len(line) != 3 or 6 could be junk or a continuation
|
||||||
|
# len(line) = 6 is package obsoletes
|
||||||
#
|
#
|
||||||
# FIXME: what is the '.' not in line conditional for?
|
# FIXME: what is the '.' not in line conditional for?
|
||||||
|
|
||||||
if '*' in line or len(line) != 3 or '.' not in line[0]:
|
if '*' in line or len(line) not in [3, 6] or '.' not in line[0]:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
pkg, version, repo = line
|
pkg, version, repo = line[0], line[1], line[2]
|
||||||
name, dist = pkg.rsplit('.', 1)
|
name, dist = pkg.rsplit('.', 1)
|
||||||
updates.update({name: {'version': version, 'dist': dist, 'repo': repo}})
|
updates.update({name: {'version': version, 'dist': dist, 'repo': repo}})
|
||||||
return updates
|
|
||||||
|
if len(line) == 6:
|
||||||
|
obsolete_pkg, obsolete_version, obsolete_repo = line[3], line[4], line[5]
|
||||||
|
obsolete_name, obsolete_dist = obsolete_pkg.rsplit('.', 1)
|
||||||
|
obsoletes.update({obsolete_name: {'version': obsolete_version, 'dist': obsolete_dist, 'repo': obsolete_repo}})
|
||||||
|
|
||||||
|
return updates, obsoletes
|
||||||
|
|
||||||
def latest(self, items, repoq):
|
def latest(self, items, repoq):
|
||||||
|
|
||||||
|
@ -1122,6 +1130,7 @@ class YumModule(YumDnf):
|
||||||
pkgs['update'] = []
|
pkgs['update'] = []
|
||||||
pkgs['install'] = []
|
pkgs['install'] = []
|
||||||
updates = {}
|
updates = {}
|
||||||
|
obsoletes = {}
|
||||||
update_all = False
|
update_all = False
|
||||||
cmd = None
|
cmd = None
|
||||||
|
|
||||||
|
@ -1135,7 +1144,7 @@ class YumModule(YumDnf):
|
||||||
res['results'].append('Nothing to do here, all packages are up to date')
|
res['results'].append('Nothing to do here, all packages are up to date')
|
||||||
return res
|
return res
|
||||||
elif rc == 100:
|
elif rc == 100:
|
||||||
updates = self.parse_check_update(out)
|
updates, obsoletes = self.parse_check_update(out)
|
||||||
elif rc == 1:
|
elif rc == 1:
|
||||||
res['msg'] = err
|
res['msg'] = err
|
||||||
res['rc'] = rc
|
res['rc'] = rc
|
||||||
|
@ -1267,6 +1276,9 @@ class YumModule(YumDnf):
|
||||||
if will_update or pkgs['install']:
|
if will_update or pkgs['install']:
|
||||||
res['changed'] = True
|
res['changed'] = True
|
||||||
|
|
||||||
|
if obsoletes:
|
||||||
|
res['obsoletes'] = obsoletes
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# run commands
|
# run commands
|
||||||
|
@ -1291,6 +1303,9 @@ class YumModule(YumDnf):
|
||||||
if rc:
|
if rc:
|
||||||
res['failed'] = True
|
res['failed'] = True
|
||||||
|
|
||||||
|
if obsoletes:
|
||||||
|
res['obsoletes'] = obsoletes
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def ensure(self, repoq):
|
def ensure(self, repoq):
|
||||||
|
|
|
@ -127,9 +127,19 @@ glibc.x86_64 2.17-157.el7_3.1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
|
|
||||||
unwrapped_output_rhel7_obsoletes = unwrapped_output_rhel7 + wrapped_output_rhel7_obsoletes_postfix
|
unwrapped_output_rhel7_obsoletes = unwrapped_output_rhel7 + wrapped_output_rhel7_obsoletes_postfix
|
||||||
unwrapped_output_rhel7_expected_pkgs = ["NetworkManager-openvpn", "NetworkManager-openvpn-gnome", "cabal-install",
|
unwrapped_output_rhel7_expected_new_obsoletes_pkgs = [
|
||||||
|
"ddashboard", "python-bugzilla", "python2-futures", "python2-pip",
|
||||||
|
"python2-pyxdg", "python2-simplejson"
|
||||||
|
]
|
||||||
|
unwrapped_output_rhel7_expected_old_obsoletes_pkgs = [
|
||||||
|
"developerdashboard", "python-bugzilla-develdashboardfixes",
|
||||||
|
"python-futures", "python-pip", "pyxdg", "python-simplejson"
|
||||||
|
]
|
||||||
|
unwrapped_output_rhel7_expected_updated_pkgs = [
|
||||||
|
"NetworkManager-openvpn", "NetworkManager-openvpn-gnome", "cabal-install",
|
||||||
"cgit", "python34-libs", "python34-test", "python34-tkinter",
|
"cgit", "python34-libs", "python34-test", "python34-tkinter",
|
||||||
"python34-tools", "qgit", "rdiff-backup", "stoken-libs", "xlockmore"]
|
"python34-tools", "qgit", "rdiff-backup", "stoken-libs", "xlockmore"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestYumUpdateCheckParse(unittest.TestCase):
|
class TestYumUpdateCheckParse(unittest.TestCase):
|
||||||
|
@ -141,34 +151,34 @@ class TestYumUpdateCheckParse(unittest.TestCase):
|
||||||
self.assertIsInstance(result, dict)
|
self.assertIsInstance(result, dict)
|
||||||
|
|
||||||
def test_empty_output(self):
|
def test_empty_output(self):
|
||||||
res = YumModule.parse_check_update("")
|
res, obs = YumModule.parse_check_update("")
|
||||||
expected_pkgs = []
|
expected_pkgs = []
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_longname(self):
|
def test_longname(self):
|
||||||
res = YumModule.parse_check_update(longname)
|
res, obs = YumModule.parse_check_update(longname)
|
||||||
expected_pkgs = ['xxxxxxxxxxxxxxxxxxxxxxxxxx', 'glibc']
|
expected_pkgs = ['xxxxxxxxxxxxxxxxxxxxxxxxxx', 'glibc']
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_plugin_load_error(self):
|
def test_plugin_load_error(self):
|
||||||
res = YumModule.parse_check_update(yum_plugin_load_error)
|
res, obs = YumModule.parse_check_update(yum_plugin_load_error)
|
||||||
expected_pkgs = []
|
expected_pkgs = []
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_wrapped_output_1(self):
|
def test_wrapped_output_1(self):
|
||||||
res = YumModule.parse_check_update(wrapped_output_1)
|
res, obs = YumModule.parse_check_update(wrapped_output_1)
|
||||||
expected_pkgs = ["vms-agent"]
|
expected_pkgs = ["vms-agent"]
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_wrapped_output_2(self):
|
def test_wrapped_output_2(self):
|
||||||
res = YumModule.parse_check_update(wrapped_output_2)
|
res, obs = YumModule.parse_check_update(wrapped_output_2)
|
||||||
expected_pkgs = ["empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty",
|
expected_pkgs = ["empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty-empty",
|
||||||
"libtiff"]
|
"libtiff"]
|
||||||
|
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_wrapped_output_3(self):
|
def test_wrapped_output_3(self):
|
||||||
res = YumModule.parse_check_update(wrapped_output_3)
|
res, obs = YumModule.parse_check_update(wrapped_output_3)
|
||||||
expected_pkgs = ["ceph", "ceph-base", "ceph-common", "ceph-mds",
|
expected_pkgs = ["ceph", "ceph-base", "ceph-common", "ceph-mds",
|
||||||
"ceph-mon", "ceph-osd", "ceph-selinux", "libcephfs1",
|
"ceph-mon", "ceph-osd", "ceph-selinux", "libcephfs1",
|
||||||
"librados2", "libradosstriper1", "librbd1", "librgw2",
|
"librados2", "libradosstriper1", "librbd1", "librgw2",
|
||||||
|
@ -176,16 +186,20 @@ class TestYumUpdateCheckParse(unittest.TestCase):
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_wrapped_output_4(self):
|
def test_wrapped_output_4(self):
|
||||||
res = YumModule.parse_check_update(wrapped_output_4)
|
res, obs = YumModule.parse_check_update(wrapped_output_4)
|
||||||
|
|
||||||
expected_pkgs = ["ipxe-roms-qemu", "quota", "quota-nls", "rdma", "screen",
|
expected_pkgs = ["ipxe-roms-qemu", "quota", "quota-nls", "rdma", "screen",
|
||||||
"sos", "sssd-client"]
|
"sos", "sssd-client"]
|
||||||
self._assert_expected(expected_pkgs, res)
|
self._assert_expected(expected_pkgs, res)
|
||||||
|
|
||||||
def test_wrapped_output_rhel7(self):
|
def test_wrapped_output_rhel7(self):
|
||||||
res = YumModule.parse_check_update(unwrapped_output_rhel7)
|
res, obs = YumModule.parse_check_update(unwrapped_output_rhel7)
|
||||||
self._assert_expected(unwrapped_output_rhel7_expected_pkgs, res)
|
self._assert_expected(unwrapped_output_rhel7_expected_updated_pkgs, res)
|
||||||
|
|
||||||
def test_wrapped_output_rhel7_obsoletes(self):
|
def test_wrapped_output_rhel7_obsoletes(self):
|
||||||
res = YumModule.parse_check_update(unwrapped_output_rhel7_obsoletes)
|
res, obs = YumModule.parse_check_update(unwrapped_output_rhel7_obsoletes)
|
||||||
self._assert_expected(unwrapped_output_rhel7_expected_pkgs, res)
|
self._assert_expected(
|
||||||
|
unwrapped_output_rhel7_expected_updated_pkgs + unwrapped_output_rhel7_expected_new_obsoletes_pkgs,
|
||||||
|
res
|
||||||
|
)
|
||||||
|
self._assert_expected(unwrapped_output_rhel7_expected_old_obsoletes_pkgs, obs)
|
||||||
|
|
Loading…
Reference in a new issue