1
0

test_yumpkg.py 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619
  1. # -*- coding: utf-8 -*-
  2. # Import Python Libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import os
  5. import salt.modules.pkg_resource as pkg_resource
  6. import salt.modules.rpm_lowpkg as rpm
  7. import salt.modules.yumpkg as yumpkg
  8. # Import Salt libs
  9. from salt.exceptions import CommandExecutionError
  10. from salt.ext import six
  11. # Import Salt Testing Libs
  12. from tests.support.mixins import LoaderModuleMockMixin
  13. from tests.support.mock import MagicMock, Mock, patch
  14. from tests.support.unit import TestCase, skipIf
  15. try:
  16. import pytest
  17. except ImportError:
  18. pytest = None
  19. LIST_REPOS = {
  20. "base": {
  21. "file": "/etc/yum.repos.d/CentOS-Base.repo",
  22. "gpgcheck": "1",
  23. "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7",
  24. "mirrorlist": "http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra",
  25. "name": "CentOS-$releasever - Base",
  26. },
  27. "base-source": {
  28. "baseurl": "http://vault.centos.org/centos/$releasever/os/Source/",
  29. "enabled": "0",
  30. "file": "/etc/yum.repos.d/CentOS-Sources.repo",
  31. "gpgcheck": "1",
  32. "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7",
  33. "name": "CentOS-$releasever - Base Sources",
  34. },
  35. "updates": {
  36. "file": "/etc/yum.repos.d/CentOS-Base.repo",
  37. "gpgcheck": "1",
  38. "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7",
  39. "mirrorlist": "http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra",
  40. "name": "CentOS-$releasever - Updates",
  41. },
  42. "updates-source": {
  43. "baseurl": "http://vault.centos.org/centos/$releasever/updates/Source/",
  44. "enabled": "0",
  45. "file": "/etc/yum.repos.d/CentOS-Sources.repo",
  46. "gpgcheck": "1",
  47. "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7",
  48. "name": "CentOS-$releasever - Updates Sources",
  49. },
  50. }
  51. class YumTestCase(TestCase, LoaderModuleMockMixin):
  52. """
  53. Test cases for salt.modules.yumpkg
  54. """
  55. def setup_loader_modules(self):
  56. return {
  57. yumpkg: {
  58. "__context__": {"yum_bin": "yum"},
  59. "__grains__": {
  60. "osarch": "x86_64",
  61. "os": "CentOS",
  62. "os_family": "RedHat",
  63. "osmajorrelease": 7,
  64. },
  65. },
  66. pkg_resource: {},
  67. }
  68. def test_list_pkgs(self):
  69. """
  70. Test packages listing.
  71. :return:
  72. """
  73. def _add_data(data, key, value):
  74. data.setdefault(key, []).append(value)
  75. rpm_out = [
  76. "python-urlgrabber_|-(none)_|-3.10_|-8.el7_|-noarch_|-(none)_|-1487838471",
  77. "alsa-lib_|-(none)_|-1.1.1_|-1.el7_|-x86_64_|-(none)_|-1487838475",
  78. "gnupg2_|-(none)_|-2.0.22_|-4.el7_|-x86_64_|-(none)_|-1487838477",
  79. "rpm-python_|-(none)_|-4.11.3_|-21.el7_|-x86_64_|-(none)_|-1487838477",
  80. "pygpgme_|-(none)_|-0.3_|-9.el7_|-x86_64_|-(none)_|-1487838478",
  81. "yum_|-(none)_|-3.4.3_|-150.el7.centos_|-noarch_|-(none)_|-1487838479",
  82. "lzo_|-(none)_|-2.06_|-8.el7_|-x86_64_|-(none)_|-1487838479",
  83. "qrencode-libs_|-(none)_|-3.4.1_|-3.el7_|-x86_64_|-(none)_|-1487838480",
  84. "ustr_|-(none)_|-1.0.4_|-16.el7_|-x86_64_|-(none)_|-1487838480",
  85. "shadow-utils_|-2_|-4.1.5.1_|-24.el7_|-x86_64_|-(none)_|-1487838481",
  86. "util-linux_|-(none)_|-2.23.2_|-33.el7_|-x86_64_|-(none)_|-1487838484",
  87. "openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485",
  88. "virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486",
  89. ]
  90. with patch.dict(yumpkg.__grains__, {"osarch": "x86_64"}), patch.dict(
  91. yumpkg.__salt__,
  92. {"cmd.run": MagicMock(return_value=os.linesep.join(rpm_out))},
  93. ), patch.dict(yumpkg.__salt__, {"pkg_resource.add_pkg": _add_data}), patch.dict(
  94. yumpkg.__salt__,
  95. {"pkg_resource.format_pkg_list": pkg_resource.format_pkg_list},
  96. ), patch.dict(
  97. yumpkg.__salt__, {"pkg_resource.stringify": MagicMock()}
  98. ), patch.dict(
  99. pkg_resource.__salt__, {"pkg.parse_arch": yumpkg.parse_arch}
  100. ):
  101. pkgs = yumpkg.list_pkgs(versions_as_list=True)
  102. for pkg_name, pkg_version in {
  103. "python-urlgrabber": "3.10-8.el7",
  104. "alsa-lib": "1.1.1-1.el7",
  105. "gnupg2": "2.0.22-4.el7",
  106. "rpm-python": "4.11.3-21.el7",
  107. "pygpgme": "0.3-9.el7",
  108. "yum": "3.4.3-150.el7.centos",
  109. "lzo": "2.06-8.el7",
  110. "qrencode-libs": "3.4.1-3.el7",
  111. "ustr": "1.0.4-16.el7",
  112. "shadow-utils": "2:4.1.5.1-24.el7",
  113. "util-linux": "2.23.2-33.el7",
  114. "openssh": "6.6.1p1-33.el7_3",
  115. "virt-what": "1.13-8.el7",
  116. }.items():
  117. self.assertTrue(pkgs.get(pkg_name))
  118. self.assertEqual(pkgs[pkg_name], [pkg_version])
  119. def test_list_pkgs_with_attr(self):
  120. """
  121. Test packages listing with the attr parameter
  122. :return:
  123. """
  124. def _add_data(data, key, value):
  125. data.setdefault(key, []).append(value)
  126. rpm_out = [
  127. "python-urlgrabber_|-(none)_|-3.10_|-8.el7_|-noarch_|-(none)_|-1487838471",
  128. "alsa-lib_|-(none)_|-1.1.1_|-1.el7_|-x86_64_|-(none)_|-1487838475",
  129. "gnupg2_|-(none)_|-2.0.22_|-4.el7_|-x86_64_|-(none)_|-1487838477",
  130. "rpm-python_|-(none)_|-4.11.3_|-21.el7_|-x86_64_|-(none)_|-1487838477",
  131. "pygpgme_|-(none)_|-0.3_|-9.el7_|-x86_64_|-(none)_|-1487838478",
  132. "yum_|-(none)_|-3.4.3_|-150.el7.centos_|-noarch_|-(none)_|-1487838479",
  133. "lzo_|-(none)_|-2.06_|-8.el7_|-x86_64_|-(none)_|-1487838479",
  134. "qrencode-libs_|-(none)_|-3.4.1_|-3.el7_|-x86_64_|-(none)_|-1487838480",
  135. "ustr_|-(none)_|-1.0.4_|-16.el7_|-x86_64_|-(none)_|-1487838480",
  136. "shadow-utils_|-2_|-4.1.5.1_|-24.el7_|-x86_64_|-(none)_|-1487838481",
  137. "util-linux_|-(none)_|-2.23.2_|-33.el7_|-x86_64_|-(none)_|-1487838484",
  138. "openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485",
  139. "virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486",
  140. ]
  141. with patch.dict(yumpkg.__grains__, {"osarch": "x86_64"}), patch.dict(
  142. yumpkg.__salt__,
  143. {"cmd.run": MagicMock(return_value=os.linesep.join(rpm_out))},
  144. ), patch.dict(yumpkg.__salt__, {"pkg_resource.add_pkg": _add_data}), patch.dict(
  145. yumpkg.__salt__,
  146. {"pkg_resource.format_pkg_list": pkg_resource.format_pkg_list},
  147. ), patch.dict(
  148. yumpkg.__salt__, {"pkg_resource.stringify": MagicMock()}
  149. ), patch.dict(
  150. pkg_resource.__salt__, {"pkg.parse_arch": yumpkg.parse_arch}
  151. ):
  152. pkgs = yumpkg.list_pkgs(
  153. attr=["epoch", "release", "arch", "install_date_time_t"]
  154. )
  155. for pkg_name, pkg_attr in {
  156. "python-urlgrabber": {
  157. "version": "3.10",
  158. "release": "8.el7",
  159. "arch": "noarch",
  160. "install_date_time_t": 1487838471,
  161. "epoch": None,
  162. },
  163. "alsa-lib": {
  164. "version": "1.1.1",
  165. "release": "1.el7",
  166. "arch": "x86_64",
  167. "install_date_time_t": 1487838475,
  168. "epoch": None,
  169. },
  170. "gnupg2": {
  171. "version": "2.0.22",
  172. "release": "4.el7",
  173. "arch": "x86_64",
  174. "install_date_time_t": 1487838477,
  175. "epoch": None,
  176. },
  177. "rpm-python": {
  178. "version": "4.11.3",
  179. "release": "21.el7",
  180. "arch": "x86_64",
  181. "install_date_time_t": 1487838477,
  182. "epoch": None,
  183. },
  184. "pygpgme": {
  185. "version": "0.3",
  186. "release": "9.el7",
  187. "arch": "x86_64",
  188. "install_date_time_t": 1487838478,
  189. "epoch": None,
  190. },
  191. "yum": {
  192. "version": "3.4.3",
  193. "release": "150.el7.centos",
  194. "arch": "noarch",
  195. "install_date_time_t": 1487838479,
  196. "epoch": None,
  197. },
  198. "lzo": {
  199. "version": "2.06",
  200. "release": "8.el7",
  201. "arch": "x86_64",
  202. "install_date_time_t": 1487838479,
  203. "epoch": None,
  204. },
  205. "qrencode-libs": {
  206. "version": "3.4.1",
  207. "release": "3.el7",
  208. "arch": "x86_64",
  209. "install_date_time_t": 1487838480,
  210. "epoch": None,
  211. },
  212. "ustr": {
  213. "version": "1.0.4",
  214. "release": "16.el7",
  215. "arch": "x86_64",
  216. "install_date_time_t": 1487838480,
  217. "epoch": None,
  218. },
  219. "shadow-utils": {
  220. "epoch": "2",
  221. "version": "4.1.5.1",
  222. "release": "24.el7",
  223. "arch": "x86_64",
  224. "install_date_time_t": 1487838481,
  225. },
  226. "util-linux": {
  227. "version": "2.23.2",
  228. "release": "33.el7",
  229. "arch": "x86_64",
  230. "install_date_time_t": 1487838484,
  231. "epoch": None,
  232. },
  233. "openssh": {
  234. "version": "6.6.1p1",
  235. "release": "33.el7_3",
  236. "arch": "x86_64",
  237. "install_date_time_t": 1487838485,
  238. "epoch": None,
  239. },
  240. "virt-what": {
  241. "version": "1.13",
  242. "release": "8.el7",
  243. "install_date_time_t": 1487838486,
  244. "arch": "x86_64",
  245. "epoch": None,
  246. },
  247. }.items():
  248. self.assertTrue(pkgs.get(pkg_name))
  249. self.assertEqual(pkgs[pkg_name], [pkg_attr])
  250. def test_list_pkgs_with_attr_multiple_versions(self):
  251. """
  252. Test packages listing with the attr parameter reporting multiple version installed
  253. :return:
  254. """
  255. def _add_data(data, key, value):
  256. data.setdefault(key, []).append(value)
  257. rpm_out = [
  258. "glibc_|-(none)_|-2.12_|-1.212.el6_|-i686_|-(none)_|-1542394210"
  259. "glibc_|-(none)_|-2.12_|-1.212.el6_|-x86_64_|-(none)_|-1542394204",
  260. "virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486",
  261. "virt-what_|-(none)_|-1.10_|-2.el7_|-x86_64_|-(none)_|-1387838486",
  262. ]
  263. with patch.dict(yumpkg.__grains__, {"osarch": "x86_64"}), patch.dict(
  264. yumpkg.__salt__,
  265. {"cmd.run": MagicMock(return_value=os.linesep.join(rpm_out))},
  266. ), patch.dict(yumpkg.__salt__, {"pkg_resource.add_pkg": _add_data}), patch.dict(
  267. yumpkg.__salt__,
  268. {"pkg_resource.format_pkg_list": pkg_resource.format_pkg_list},
  269. ), patch.dict(
  270. yumpkg.__salt__, {"pkg_resource.stringify": MagicMock()}
  271. ), patch.dict(
  272. pkg_resource.__salt__, {"pkg.parse_arch": yumpkg.parse_arch}
  273. ):
  274. pkgs = yumpkg.list_pkgs(
  275. attr=["epoch", "release", "arch", "install_date_time_t"]
  276. )
  277. expected_pkg_list = {
  278. "glibc": [
  279. {
  280. "version": "2.12",
  281. "release": "1.212.el6",
  282. "install_date_time_t": 1542394210,
  283. "arch": "i686",
  284. "epoch": None,
  285. },
  286. {
  287. "version": "2.12",
  288. "release": "1.212.el6",
  289. "install_date_time_t": 1542394204,
  290. "arch": "x86_64",
  291. "epoch": None,
  292. },
  293. ],
  294. "virt-what": [
  295. {
  296. "version": "1.10",
  297. "release": "2.el7",
  298. "install_date_time_t": 1387838486,
  299. "arch": "x86_64",
  300. "epoch": None,
  301. },
  302. {
  303. "version": "1.13",
  304. "release": "8.el7",
  305. "install_date_time_t": 1487838486,
  306. "arch": "x86_64",
  307. "epoch": None,
  308. },
  309. ],
  310. }
  311. for pkgname, pkginfo in pkgs.items():
  312. if six.PY3:
  313. self.assertCountEqual(pkginfo, expected_pkg_list[pkgname])
  314. else:
  315. self.assertItemsEqual(pkginfo, expected_pkg_list[pkgname])
  316. def test_list_patches(self):
  317. """
  318. Test patches listing.
  319. :return:
  320. """
  321. yum_out = [
  322. "i my-fake-patch-not-installed-1234 recommended spacewalk-usix-2.7.5.2-2.2.noarch",
  323. " my-fake-patch-not-installed-1234 recommended spacewalksd-5.0.26.2-21.2.x86_64",
  324. "i my-fake-patch-not-installed-1234 recommended suseRegisterInfo-3.1.1-18.2.x86_64",
  325. "i my-fake-patch-installed-1234 recommended my-package-one-1.1-0.1.x86_64",
  326. "i my-fake-patch-installed-1234 recommended my-package-two-1.1-0.1.x86_64",
  327. ]
  328. expected_patches = {
  329. "my-fake-patch-not-installed-1234": {
  330. "installed": False,
  331. "summary": [
  332. "spacewalk-usix-2.7.5.2-2.2.noarch",
  333. "spacewalksd-5.0.26.2-21.2.x86_64",
  334. "suseRegisterInfo-3.1.1-18.2.x86_64",
  335. ],
  336. },
  337. "my-fake-patch-installed-1234": {
  338. "installed": True,
  339. "summary": [
  340. "my-package-one-1.1-0.1.x86_64",
  341. "my-package-two-1.1-0.1.x86_64",
  342. ],
  343. },
  344. }
  345. with patch.dict(yumpkg.__grains__, {"osarch": "x86_64"}), patch.dict(
  346. yumpkg.__salt__,
  347. {"cmd.run_stdout": MagicMock(return_value=os.linesep.join(yum_out))},
  348. ):
  349. patches = yumpkg.list_patches()
  350. self.assertFalse(patches["my-fake-patch-not-installed-1234"]["installed"])
  351. self.assertTrue(
  352. len(patches["my-fake-patch-not-installed-1234"]["summary"]) == 3
  353. )
  354. for _patch in expected_patches["my-fake-patch-not-installed-1234"][
  355. "summary"
  356. ]:
  357. self.assertTrue(
  358. _patch in patches["my-fake-patch-not-installed-1234"]["summary"]
  359. )
  360. self.assertTrue(patches["my-fake-patch-installed-1234"]["installed"])
  361. self.assertTrue(
  362. len(patches["my-fake-patch-installed-1234"]["summary"]) == 2
  363. )
  364. for _patch in expected_patches["my-fake-patch-installed-1234"]["summary"]:
  365. self.assertTrue(
  366. _patch in patches["my-fake-patch-installed-1234"]["summary"]
  367. )
  368. def test_latest_version_with_options(self):
  369. with patch.object(yumpkg, "list_pkgs", MagicMock(return_value={})):
  370. # with fromrepo
  371. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  372. with patch.dict(
  373. yumpkg.__salt__,
  374. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  375. ):
  376. yumpkg.latest_version(
  377. "foo", refresh=False, fromrepo="good", branch="foo"
  378. )
  379. cmd.assert_called_once_with(
  380. [
  381. "yum",
  382. "--quiet",
  383. "--disablerepo=*",
  384. "--enablerepo=good",
  385. "--branch=foo",
  386. "list",
  387. "available",
  388. "foo",
  389. ],
  390. env={},
  391. ignore_retcode=True,
  392. output_loglevel="trace",
  393. python_shell=False,
  394. )
  395. # without fromrepo
  396. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  397. with patch.dict(
  398. yumpkg.__salt__,
  399. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  400. ):
  401. yumpkg.latest_version(
  402. "foo",
  403. refresh=False,
  404. enablerepo="good",
  405. disablerepo="bad",
  406. branch="foo",
  407. )
  408. cmd.assert_called_once_with(
  409. [
  410. "yum",
  411. "--quiet",
  412. "--disablerepo=bad",
  413. "--enablerepo=good",
  414. "--branch=foo",
  415. "list",
  416. "available",
  417. "foo",
  418. ],
  419. env={},
  420. ignore_retcode=True,
  421. output_loglevel="trace",
  422. python_shell=False,
  423. )
  424. # without fromrepo, but within the scope
  425. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  426. with patch("salt.utils.systemd.has_scope", MagicMock(return_value=True)):
  427. with patch.dict(
  428. yumpkg.__salt__,
  429. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=True)},
  430. ):
  431. yumpkg.latest_version(
  432. "foo",
  433. refresh=False,
  434. enablerepo="good",
  435. disablerepo="bad",
  436. branch="foo",
  437. )
  438. cmd.assert_called_once_with(
  439. [
  440. "systemd-run",
  441. "--scope",
  442. "yum",
  443. "--quiet",
  444. "--disablerepo=bad",
  445. "--enablerepo=good",
  446. "--branch=foo",
  447. "list",
  448. "available",
  449. "foo",
  450. ],
  451. env={},
  452. ignore_retcode=True,
  453. output_loglevel="trace",
  454. python_shell=False,
  455. )
  456. def test_list_repo_pkgs_with_options(self):
  457. """
  458. Test list_repo_pkgs with and without fromrepo
  459. NOTE: mock_calls is a stack. The most recent call is indexed
  460. with 0, while the first call would have the highest index.
  461. """
  462. really_old_yum = MagicMock(return_value="3.2.0")
  463. older_yum = MagicMock(return_value="3.4.0")
  464. newer_yum = MagicMock(return_value="3.4.5")
  465. list_repos_mock = MagicMock(return_value=LIST_REPOS)
  466. kwargs = {
  467. "output_loglevel": "trace",
  468. "ignore_retcode": True,
  469. "python_shell": False,
  470. "env": {},
  471. }
  472. with patch.object(yumpkg, "list_repos", list_repos_mock):
  473. # Test with really old yum. The fromrepo argument has no effect on
  474. # the yum commands we'd run.
  475. with patch.dict(yumpkg.__salt__, {"cmd.run": really_old_yum}):
  476. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  477. with patch.dict(
  478. yumpkg.__salt__,
  479. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  480. ):
  481. yumpkg.list_repo_pkgs("foo")
  482. # We should have called cmd.run_all twice
  483. assert len(cmd.mock_calls) == 2
  484. # Check args from first call
  485. assert cmd.mock_calls[1][1] == (
  486. ["yum", "--quiet", "list", "available"],
  487. )
  488. # Check kwargs from first call
  489. assert cmd.mock_calls[1][2] == kwargs
  490. # Check args from second call
  491. assert cmd.mock_calls[0][1] == (
  492. ["yum", "--quiet", "list", "installed"],
  493. )
  494. # Check kwargs from second call
  495. assert cmd.mock_calls[0][2] == kwargs
  496. # Test with really old yum. The fromrepo argument has no effect on
  497. # the yum commands we'd run.
  498. with patch.dict(yumpkg.__salt__, {"cmd.run": older_yum}):
  499. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  500. with patch.dict(
  501. yumpkg.__salt__,
  502. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  503. ):
  504. yumpkg.list_repo_pkgs("foo")
  505. # We should have called cmd.run_all twice
  506. assert len(cmd.mock_calls) == 2
  507. # Check args from first call
  508. assert cmd.mock_calls[1][1] == (
  509. ["yum", "--quiet", "--showduplicates", "list", "available"],
  510. )
  511. # Check kwargs from first call
  512. assert cmd.mock_calls[1][2] == kwargs
  513. # Check args from second call
  514. assert cmd.mock_calls[0][1] == (
  515. ["yum", "--quiet", "--showduplicates", "list", "installed"],
  516. )
  517. # Check kwargs from second call
  518. assert cmd.mock_calls[0][2] == kwargs
  519. # Test with newer yum. We should run one yum command per repo, so
  520. # fromrepo would limit how many calls we make.
  521. with patch.dict(yumpkg.__salt__, {"cmd.run": newer_yum}):
  522. # When fromrepo is used, we would only run one yum command, for
  523. # that specific repo.
  524. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  525. with patch.dict(
  526. yumpkg.__salt__,
  527. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  528. ):
  529. yumpkg.list_repo_pkgs("foo", fromrepo="base")
  530. # We should have called cmd.run_all once
  531. assert len(cmd.mock_calls) == 1
  532. # Check args
  533. assert cmd.mock_calls[0][1] == (
  534. [
  535. "yum",
  536. "--quiet",
  537. "--showduplicates",
  538. "repository-packages",
  539. "base",
  540. "list",
  541. "foo",
  542. ],
  543. )
  544. # Check kwargs
  545. assert cmd.mock_calls[0][2] == kwargs
  546. # Test enabling base-source and disabling updates. We should
  547. # get two calls, one for each enabled repo. Because dict
  548. # iteration order will vary, different Python versions will be
  549. # do them in different orders, which is OK, but it will just
  550. # mean that we will have to check both the first and second
  551. # mock call both times.
  552. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  553. with patch.dict(
  554. yumpkg.__salt__,
  555. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  556. ):
  557. yumpkg.list_repo_pkgs(
  558. "foo", enablerepo="base-source", disablerepo="updates"
  559. )
  560. # We should have called cmd.run_all twice
  561. assert len(cmd.mock_calls) == 2
  562. for repo in ("base", "base-source"):
  563. for index in (0, 1):
  564. try:
  565. # Check args
  566. assert cmd.mock_calls[index][1] == (
  567. [
  568. "yum",
  569. "--quiet",
  570. "--showduplicates",
  571. "repository-packages",
  572. repo,
  573. "list",
  574. "foo",
  575. ],
  576. )
  577. # Check kwargs
  578. assert cmd.mock_calls[index][2] == kwargs
  579. break
  580. except AssertionError:
  581. continue
  582. else:
  583. self.fail("repo '{0}' not checked".format(repo))
  584. def test_list_upgrades_dnf(self):
  585. """
  586. The subcommand should be "upgrades" with dnf
  587. """
  588. with patch.dict(yumpkg.__context__, {"yum_bin": "dnf"}):
  589. # with fromrepo
  590. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  591. with patch.dict(
  592. yumpkg.__salt__,
  593. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  594. ):
  595. yumpkg.list_upgrades(refresh=False, fromrepo="good", branch="foo")
  596. cmd.assert_called_once_with(
  597. [
  598. "dnf",
  599. "--quiet",
  600. "--disablerepo=*",
  601. "--enablerepo=good",
  602. "--branch=foo",
  603. "list",
  604. "upgrades",
  605. ],
  606. env={},
  607. output_loglevel="trace",
  608. ignore_retcode=True,
  609. python_shell=False,
  610. )
  611. # without fromrepo
  612. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  613. with patch.dict(
  614. yumpkg.__salt__,
  615. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  616. ):
  617. yumpkg.list_upgrades(
  618. refresh=False, enablerepo="good", disablerepo="bad", branch="foo"
  619. )
  620. cmd.assert_called_once_with(
  621. [
  622. "dnf",
  623. "--quiet",
  624. "--disablerepo=bad",
  625. "--enablerepo=good",
  626. "--branch=foo",
  627. "list",
  628. "upgrades",
  629. ],
  630. env={},
  631. output_loglevel="trace",
  632. ignore_retcode=True,
  633. python_shell=False,
  634. )
  635. def test_list_upgrades_yum(self):
  636. """
  637. The subcommand should be "updates" with yum
  638. """
  639. # with fromrepo
  640. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  641. with patch.dict(
  642. yumpkg.__salt__,
  643. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  644. ):
  645. yumpkg.list_upgrades(refresh=False, fromrepo="good", branch="foo")
  646. cmd.assert_called_once_with(
  647. [
  648. "yum",
  649. "--quiet",
  650. "--disablerepo=*",
  651. "--enablerepo=good",
  652. "--branch=foo",
  653. "list",
  654. "updates",
  655. ],
  656. env={},
  657. output_loglevel="trace",
  658. ignore_retcode=True,
  659. python_shell=False,
  660. )
  661. # without fromrepo
  662. cmd = MagicMock(return_value={"retcode": 0, "stdout": ""})
  663. with patch.dict(
  664. yumpkg.__salt__,
  665. {"cmd.run_all": cmd, "config.get": MagicMock(return_value=False)},
  666. ):
  667. yumpkg.list_upgrades(
  668. refresh=False, enablerepo="good", disablerepo="bad", branch="foo"
  669. )
  670. cmd.assert_called_once_with(
  671. [
  672. "yum",
  673. "--quiet",
  674. "--disablerepo=bad",
  675. "--enablerepo=good",
  676. "--branch=foo",
  677. "list",
  678. "updates",
  679. ],
  680. env={},
  681. output_loglevel="trace",
  682. ignore_retcode=True,
  683. python_shell=False,
  684. )
  685. def test_refresh_db_with_options(self):
  686. with patch("salt.utils.pkg.clear_rtag", Mock()):
  687. # With check_update=True we will do a cmd.run to run the clean_cmd, and
  688. # then a separate cmd.retcode to check for updates.
  689. # with fromrepo
  690. yum_call = MagicMock()
  691. with patch.dict(
  692. yumpkg.__salt__,
  693. {"cmd.run_all": yum_call, "config.get": MagicMock(return_value=False)},
  694. ):
  695. yumpkg.refresh_db(check_update=True, fromrepo="good", branch="foo")
  696. assert yum_call.call_count == 2
  697. yum_call.assert_any_call(
  698. [
  699. "yum",
  700. "--quiet",
  701. "--assumeyes",
  702. "clean",
  703. "expire-cache",
  704. "--disablerepo=*",
  705. "--enablerepo=good",
  706. "--branch=foo",
  707. ],
  708. env={},
  709. ignore_retcode=True,
  710. output_loglevel="trace",
  711. python_shell=False,
  712. )
  713. yum_call.assert_any_call(
  714. [
  715. "yum",
  716. "--quiet",
  717. "--assumeyes",
  718. "check-update",
  719. "--setopt=autocheck_running_kernel=false",
  720. "--disablerepo=*",
  721. "--enablerepo=good",
  722. "--branch=foo",
  723. ],
  724. output_loglevel="trace",
  725. env={},
  726. ignore_retcode=True,
  727. python_shell=False,
  728. )
  729. # without fromrepo
  730. yum_call = MagicMock()
  731. with patch.dict(
  732. yumpkg.__salt__,
  733. {"cmd.run_all": yum_call, "config.get": MagicMock(return_value=False)},
  734. ):
  735. yumpkg.refresh_db(
  736. check_update=True,
  737. enablerepo="good",
  738. disablerepo="bad",
  739. branch="foo",
  740. )
  741. assert yum_call.call_count == 2
  742. yum_call.assert_any_call(
  743. [
  744. "yum",
  745. "--quiet",
  746. "--assumeyes",
  747. "clean",
  748. "expire-cache",
  749. "--disablerepo=bad",
  750. "--enablerepo=good",
  751. "--branch=foo",
  752. ],
  753. env={},
  754. ignore_retcode=True,
  755. output_loglevel="trace",
  756. python_shell=False,
  757. )
  758. yum_call.assert_any_call(
  759. [
  760. "yum",
  761. "--quiet",
  762. "--assumeyes",
  763. "check-update",
  764. "--setopt=autocheck_running_kernel=false",
  765. "--disablerepo=bad",
  766. "--enablerepo=good",
  767. "--branch=foo",
  768. ],
  769. output_loglevel="trace",
  770. env={},
  771. ignore_retcode=True,
  772. python_shell=False,
  773. )
  774. # With check_update=False we will just do a cmd.run for the clean_cmd
  775. # with fromrepo
  776. yum_call = MagicMock()
  777. with patch.dict(
  778. yumpkg.__salt__,
  779. {"cmd.run_all": yum_call, "config.get": MagicMock(return_value=False)},
  780. ):
  781. yumpkg.refresh_db(check_update=False, fromrepo="good", branch="foo")
  782. assert yum_call.call_count == 1
  783. yum_call.assert_called_once_with(
  784. [
  785. "yum",
  786. "--quiet",
  787. "--assumeyes",
  788. "clean",
  789. "expire-cache",
  790. "--disablerepo=*",
  791. "--enablerepo=good",
  792. "--branch=foo",
  793. ],
  794. env={},
  795. output_loglevel="trace",
  796. ignore_retcode=True,
  797. python_shell=False,
  798. )
  799. # without fromrepo
  800. yum_call = MagicMock()
  801. with patch.dict(
  802. yumpkg.__salt__,
  803. {"cmd.run_all": yum_call, "config.get": MagicMock(return_value=False)},
  804. ):
  805. yumpkg.refresh_db(
  806. check_update=False,
  807. enablerepo="good",
  808. disablerepo="bad",
  809. branch="foo",
  810. )
  811. assert yum_call.call_count == 1
  812. yum_call.assert_called_once_with(
  813. [
  814. "yum",
  815. "--quiet",
  816. "--assumeyes",
  817. "clean",
  818. "expire-cache",
  819. "--disablerepo=bad",
  820. "--enablerepo=good",
  821. "--branch=foo",
  822. ],
  823. env={},
  824. output_loglevel="trace",
  825. ignore_retcode=True,
  826. python_shell=False,
  827. )
  828. def test_install_with_options(self):
  829. parse_targets = MagicMock(return_value=({"foo": None}, "repository"))
  830. with patch.object(
  831. yumpkg, "list_pkgs", MagicMock(return_value={})
  832. ), patch.object(yumpkg, "list_holds", MagicMock(return_value=[])), patch.dict(
  833. yumpkg.__salt__, {"pkg_resource.parse_targets": parse_targets}
  834. ), patch(
  835. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  836. ):
  837. # with fromrepo
  838. cmd = MagicMock(return_value={"retcode": 0})
  839. with patch.dict(yumpkg.__salt__, {"cmd.run_all": cmd}):
  840. yumpkg.install(
  841. refresh=False,
  842. fromrepo="good",
  843. branch="foo",
  844. setopt="obsoletes=0,plugins=0",
  845. )
  846. cmd.assert_called_once_with(
  847. [
  848. "yum",
  849. "-y",
  850. "--disablerepo=*",
  851. "--enablerepo=good",
  852. "--branch=foo",
  853. "--setopt",
  854. "obsoletes=0",
  855. "--setopt",
  856. "plugins=0",
  857. "install",
  858. "foo",
  859. ],
  860. env={},
  861. output_loglevel="trace",
  862. python_shell=False,
  863. ignore_retcode=False,
  864. redirect_stderr=True,
  865. )
  866. # without fromrepo
  867. cmd = MagicMock(return_value={"retcode": 0})
  868. with patch.dict(yumpkg.__salt__, {"cmd.run_all": cmd}):
  869. yumpkg.install(
  870. refresh=False,
  871. enablerepo="good",
  872. disablerepo="bad",
  873. branch="foo",
  874. setopt="obsoletes=0,plugins=0",
  875. )
  876. cmd.assert_called_once_with(
  877. [
  878. "yum",
  879. "-y",
  880. "--disablerepo=bad",
  881. "--enablerepo=good",
  882. "--branch=foo",
  883. "--setopt",
  884. "obsoletes=0",
  885. "--setopt",
  886. "plugins=0",
  887. "install",
  888. "foo",
  889. ],
  890. env={},
  891. output_loglevel="trace",
  892. python_shell=False,
  893. ignore_retcode=False,
  894. redirect_stderr=True,
  895. )
  896. def test_install_with_epoch(self):
  897. """
  898. Tests that we properly identify a version containing an epoch as an
  899. upgrade instead of a downgrade.
  900. """
  901. name = "foo"
  902. old = "8:3.8.12-6.n.el7"
  903. new = "9:3.8.12-4.n.el7"
  904. list_pkgs_mock = MagicMock(
  905. side_effect=lambda **kwargs: {
  906. name: [old] if kwargs.get("versions_as_list", False) else old
  907. }
  908. )
  909. cmd_mock = MagicMock(
  910. return_value={"pid": 12345, "retcode": 0, "stdout": "", "stderr": ""}
  911. )
  912. salt_mock = {
  913. "cmd.run_all": cmd_mock,
  914. "lowpkg.version_cmp": rpm.version_cmp,
  915. "pkg_resource.parse_targets": MagicMock(
  916. return_value=({name: new}, "repository")
  917. ),
  918. }
  919. full_pkg_string = "-".join((name, new[2:]))
  920. with patch.object(yumpkg, "list_pkgs", list_pkgs_mock), patch(
  921. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  922. ), patch.dict(yumpkg.__salt__, salt_mock):
  923. # Test yum
  924. expected = ["yum", "-y", "install", full_pkg_string]
  925. with patch.dict(yumpkg.__grains__, {"os": "CentOS", "osrelease": 7}):
  926. yumpkg.install("foo", version=new)
  927. call = cmd_mock.mock_calls[0][1][0]
  928. assert call == expected, call
  929. # Test dnf
  930. expected = [
  931. "dnf",
  932. "-y",
  933. "--best",
  934. "--allowerasing",
  935. "install",
  936. full_pkg_string,
  937. ]
  938. yumpkg.__context__.pop("yum_bin")
  939. cmd_mock.reset_mock()
  940. with patch.dict(yumpkg.__grains__, {"os": "Fedora", "osrelease": 27}):
  941. yumpkg.install("foo", version=new)
  942. call = cmd_mock.mock_calls[0][1][0]
  943. assert call == expected, call
  944. def test_upgrade_with_options(self):
  945. with patch.object(yumpkg, "list_pkgs", MagicMock(return_value={})), patch(
  946. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  947. ):
  948. # with fromrepo
  949. cmd = MagicMock(return_value={"retcode": 0})
  950. with patch.dict(yumpkg.__salt__, {"cmd.run_all": cmd}):
  951. yumpkg.upgrade(
  952. refresh=False,
  953. fromrepo="good",
  954. exclude="kernel*",
  955. branch="foo",
  956. setopt="obsoletes=0,plugins=0",
  957. )
  958. cmd.assert_called_once_with(
  959. [
  960. "yum",
  961. "--quiet",
  962. "-y",
  963. "--disablerepo=*",
  964. "--enablerepo=good",
  965. "--branch=foo",
  966. "--setopt",
  967. "obsoletes=0",
  968. "--setopt",
  969. "plugins=0",
  970. "--exclude=kernel*",
  971. "upgrade",
  972. ],
  973. env={},
  974. output_loglevel="trace",
  975. python_shell=False,
  976. )
  977. # without fromrepo
  978. cmd = MagicMock(return_value={"retcode": 0})
  979. with patch.dict(yumpkg.__salt__, {"cmd.run_all": cmd}):
  980. yumpkg.upgrade(
  981. refresh=False,
  982. enablerepo="good",
  983. disablerepo="bad",
  984. exclude="kernel*",
  985. branch="foo",
  986. setopt="obsoletes=0,plugins=0",
  987. )
  988. cmd.assert_called_once_with(
  989. [
  990. "yum",
  991. "--quiet",
  992. "-y",
  993. "--disablerepo=bad",
  994. "--enablerepo=good",
  995. "--branch=foo",
  996. "--setopt",
  997. "obsoletes=0",
  998. "--setopt",
  999. "plugins=0",
  1000. "--exclude=kernel*",
  1001. "upgrade",
  1002. ],
  1003. env={},
  1004. output_loglevel="trace",
  1005. python_shell=False,
  1006. )
  1007. def test_info_installed_with_all_versions(self):
  1008. """
  1009. Test the return information of all versions for the named package(s), installed on the system.
  1010. :return:
  1011. """
  1012. run_out = {
  1013. "virgo-dummy": [
  1014. {
  1015. "build_date": "2015-07-09T10:55:19Z",
  1016. "vendor": "openSUSE Build Service",
  1017. "description": "This is the Virgo dummy package used for testing SUSE Manager",
  1018. "license": "GPL-2.0",
  1019. "build_host": "sheep05",
  1020. "url": "http://www.suse.com",
  1021. "build_date_time_t": 1436432119,
  1022. "relocations": "(not relocatable)",
  1023. "source_rpm": "virgo-dummy-1.0-1.1.src.rpm",
  1024. "install_date": "2016-02-23T16:31:57Z",
  1025. "install_date_time_t": 1456241517,
  1026. "summary": "Virgo dummy package",
  1027. "version": "1.0",
  1028. "signature": "DSA/SHA1, Thu Jul 9 08:55:33 2015, Key ID 27fa41bd8a7c64f9",
  1029. "release": "1.1",
  1030. "group": "Applications/System",
  1031. "arch": "i686",
  1032. "size": "17992",
  1033. },
  1034. {
  1035. "build_date": "2015-07-09T10:15:19Z",
  1036. "vendor": "openSUSE Build Service",
  1037. "description": "This is the Virgo dummy package used for testing SUSE Manager",
  1038. "license": "GPL-2.0",
  1039. "build_host": "sheep05",
  1040. "url": "http://www.suse.com",
  1041. "build_date_time_t": 1436432119,
  1042. "relocations": "(not relocatable)",
  1043. "source_rpm": "virgo-dummy-1.0-1.1.src.rpm",
  1044. "install_date": "2016-02-23T16:31:57Z",
  1045. "install_date_time_t": 14562415127,
  1046. "summary": "Virgo dummy package",
  1047. "version": "1.0",
  1048. "signature": "DSA/SHA1, Thu Jul 9 08:55:33 2015, Key ID 27fa41bd8a7c64f9",
  1049. "release": "1.1",
  1050. "group": "Applications/System",
  1051. "arch": "x86_64",
  1052. "size": "13124",
  1053. },
  1054. ],
  1055. "libopenssl1_0_0": [
  1056. {
  1057. "build_date": "2015-11-04T23:20:34Z",
  1058. "vendor": "SUSE LLC <https://www.suse.com/>",
  1059. "description": "The OpenSSL Project is a collaborative effort.",
  1060. "license": "OpenSSL",
  1061. "build_host": "sheep11",
  1062. "url": "https://www.openssl.org/",
  1063. "build_date_time_t": 1446675634,
  1064. "relocations": "(not relocatable)",
  1065. "source_rpm": "openssl-1.0.1i-34.1.src.rpm",
  1066. "install_date": "2016-02-23T16:31:35Z",
  1067. "install_date_time_t": 1456241495,
  1068. "summary": "Secure Sockets and Transport Layer Security",
  1069. "version": "1.0.1i",
  1070. "signature": "RSA/SHA256, Wed Nov 4 22:21:34 2015, Key ID 70af9e8139db7c82",
  1071. "release": "34.1",
  1072. "group": "Productivity/Networking/Security",
  1073. "packager": "https://www.suse.com/",
  1074. "arch": "x86_64",
  1075. "size": "2576912",
  1076. }
  1077. ],
  1078. }
  1079. with patch.dict(
  1080. yumpkg.__salt__, {"lowpkg.info": MagicMock(return_value=run_out)}
  1081. ):
  1082. installed = yumpkg.info_installed(all_versions=True)
  1083. # Test overall products length
  1084. self.assertEqual(len(installed), 2)
  1085. # Test multiple versions for the same package
  1086. for pkg_name, pkg_info_list in installed.items():
  1087. self.assertEqual(
  1088. len(pkg_info_list), 2 if pkg_name == "virgo-dummy" else 1
  1089. )
  1090. for info in pkg_info_list:
  1091. self.assertTrue(info["arch"] in ("x86_64", "i686"))
  1092. def test_pkg_hold_yum(self):
  1093. """
  1094. Tests that we properly identify versionlock plugin when using yum
  1095. for RHEL/CentOS 7 and Fedora < 22
  1096. """
  1097. # Test RHEL/CentOS 7
  1098. list_pkgs_mock = {
  1099. "yum-plugin-versionlock": "0:1.0.0-0.n.el7",
  1100. "yum-versionlock": "0:1.0.0-0.n.el7",
  1101. }
  1102. cmd = MagicMock(return_value={"retcode": 0})
  1103. with patch.object(
  1104. yumpkg, "list_pkgs", MagicMock(return_value=list_pkgs_mock)
  1105. ), patch.object(yumpkg, "list_holds", MagicMock(return_value=[])), patch.dict(
  1106. yumpkg.__salt__, {"cmd.run_all": cmd}
  1107. ), patch(
  1108. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  1109. ):
  1110. yumpkg.hold("foo")
  1111. cmd.assert_called_once_with(
  1112. ["yum", "versionlock", "foo"],
  1113. env={},
  1114. output_loglevel="trace",
  1115. python_shell=False,
  1116. )
  1117. # Test Fedora 20
  1118. cmd = MagicMock(return_value={"retcode": 0})
  1119. with patch.dict(
  1120. yumpkg.__grains__, {"os": "Fedora", "osrelease": 20}
  1121. ), patch.object(
  1122. yumpkg, "list_pkgs", MagicMock(return_value=list_pkgs_mock)
  1123. ), patch.object(
  1124. yumpkg, "list_holds", MagicMock(return_value=[])
  1125. ), patch.dict(
  1126. yumpkg.__salt__, {"cmd.run_all": cmd}
  1127. ), patch(
  1128. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  1129. ):
  1130. yumpkg.hold("foo")
  1131. cmd.assert_called_once_with(
  1132. ["yum", "versionlock", "foo"],
  1133. env={},
  1134. output_loglevel="trace",
  1135. python_shell=False,
  1136. )
  1137. def test_pkg_hold_dnf(self):
  1138. """
  1139. Tests that we properly identify versionlock plugin when using dnf
  1140. for RHEL/CentOS 8 and Fedora >= 22
  1141. """
  1142. # Test RHEL/CentOS 8
  1143. list_pkgs_mock = {
  1144. "python2-dnf-plugin-versionlock": "0:1.0.0-0.n.el8",
  1145. "python3-dnf-plugin-versionlock": "0:1.0.0-0.n.el8",
  1146. }
  1147. yumpkg.__context__.pop("yum_bin")
  1148. cmd = MagicMock(return_value={"retcode": 0})
  1149. with patch.dict(yumpkg.__grains__, {"osmajorrelease": 8}), patch.object(
  1150. yumpkg, "list_pkgs", MagicMock(return_value=list_pkgs_mock)
  1151. ), patch.object(yumpkg, "list_holds", MagicMock(return_value=[])), patch.dict(
  1152. yumpkg.__salt__, {"cmd.run_all": cmd}
  1153. ), patch(
  1154. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  1155. ):
  1156. yumpkg.hold("foo")
  1157. cmd.assert_called_once_with(
  1158. ["dnf", "versionlock", "foo"],
  1159. env={},
  1160. output_loglevel="trace",
  1161. python_shell=False,
  1162. )
  1163. # Test Fedora 26+
  1164. yumpkg.__context__.pop("yum_bin")
  1165. cmd = MagicMock(return_value={"retcode": 0})
  1166. with patch.dict(
  1167. yumpkg.__grains__, {"os": "Fedora", "osrelease": 26}
  1168. ), patch.object(
  1169. yumpkg, "list_pkgs", MagicMock(return_value=list_pkgs_mock)
  1170. ), patch.object(
  1171. yumpkg, "list_holds", MagicMock(return_value=[])
  1172. ), patch.dict(
  1173. yumpkg.__salt__, {"cmd.run_all": cmd}
  1174. ), patch(
  1175. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  1176. ):
  1177. yumpkg.hold("foo")
  1178. cmd.assert_called_once_with(
  1179. ["dnf", "versionlock", "foo"],
  1180. env={},
  1181. output_loglevel="trace",
  1182. python_shell=False,
  1183. )
  1184. # Test Fedora 22-25
  1185. list_pkgs_mock = {
  1186. "python-dnf-plugins-extras-versionlock": "0:1.0.0-0.n.el8",
  1187. "python3-dnf-plugins-extras-versionlock": "0:1.0.0-0.n.el8",
  1188. }
  1189. yumpkg.__context__.pop("yum_bin")
  1190. cmd = MagicMock(return_value={"retcode": 0})
  1191. with patch.dict(
  1192. yumpkg.__grains__, {"os": "Fedora", "osrelease": 25}
  1193. ), patch.object(
  1194. yumpkg, "list_pkgs", MagicMock(return_value=list_pkgs_mock)
  1195. ), patch.object(
  1196. yumpkg, "list_holds", MagicMock(return_value=[])
  1197. ), patch.dict(
  1198. yumpkg.__salt__, {"cmd.run_all": cmd}
  1199. ), patch(
  1200. "salt.utils.systemd.has_scope", MagicMock(return_value=False)
  1201. ):
  1202. yumpkg.hold("foo")
  1203. cmd.assert_called_once_with(
  1204. ["dnf", "versionlock", "foo"],
  1205. env={},
  1206. output_loglevel="trace",
  1207. python_shell=False,
  1208. )
  1209. @skipIf(not yumpkg.HAS_YUM, "Could not import yum")
  1210. def test_yum_base_error(self):
  1211. with patch("yum.YumBase") as mock_yum_yumbase:
  1212. mock_yum_yumbase.side_effect = CommandExecutionError
  1213. with pytest.raises(CommandExecutionError):
  1214. yumpkg._get_yum_config()
  1215. def test_group_info(self):
  1216. """
  1217. Test yumpkg.group_info parsing
  1218. """
  1219. expected = {
  1220. "conditional": [],
  1221. "default": ["qgnomeplatform", "xdg-desktop-portal-gtk"],
  1222. "description": "GNOME is a highly intuitive and user friendly desktop environment.",
  1223. "group": "GNOME",
  1224. "id": "gnome-desktop",
  1225. "mandatory": [
  1226. "NetworkManager-libreswan-gnome",
  1227. "PackageKit-command-not-found",
  1228. "PackageKit-gtk3-module",
  1229. "abrt-desktop",
  1230. "at-spi2-atk",
  1231. "at-spi2-core",
  1232. "avahi",
  1233. "baobab",
  1234. "caribou",
  1235. "caribou-gtk2-module",
  1236. "caribou-gtk3-module",
  1237. "cheese",
  1238. "chrome-gnome-shell",
  1239. "compat-cheese314",
  1240. "control-center",
  1241. "dconf",
  1242. "empathy",
  1243. "eog",
  1244. "evince",
  1245. "evince-nautilus",
  1246. "file-roller",
  1247. "file-roller-nautilus",
  1248. "firewall-config",
  1249. "firstboot",
  1250. "fprintd-pam",
  1251. "gdm",
  1252. "gedit",
  1253. "glib-networking",
  1254. "gnome-bluetooth",
  1255. "gnome-boxes",
  1256. "gnome-calculator",
  1257. "gnome-classic-session",
  1258. "gnome-clocks",
  1259. "gnome-color-manager",
  1260. "gnome-contacts",
  1261. "gnome-dictionary",
  1262. "gnome-disk-utility",
  1263. "gnome-font-viewer",
  1264. "gnome-getting-started-docs",
  1265. "gnome-icon-theme",
  1266. "gnome-icon-theme-extras",
  1267. "gnome-icon-theme-symbolic",
  1268. "gnome-initial-setup",
  1269. "gnome-packagekit",
  1270. "gnome-packagekit-updater",
  1271. "gnome-screenshot",
  1272. "gnome-session",
  1273. "gnome-session-xsession",
  1274. "gnome-settings-daemon",
  1275. "gnome-shell",
  1276. "gnome-software",
  1277. "gnome-system-log",
  1278. "gnome-system-monitor",
  1279. "gnome-terminal",
  1280. "gnome-terminal-nautilus",
  1281. "gnome-themes-standard",
  1282. "gnome-tweak-tool",
  1283. "gnome-user-docs",
  1284. "gnome-weather",
  1285. "gucharmap",
  1286. "gvfs-afc",
  1287. "gvfs-afp",
  1288. "gvfs-archive",
  1289. "gvfs-fuse",
  1290. "gvfs-goa",
  1291. "gvfs-gphoto2",
  1292. "gvfs-mtp",
  1293. "gvfs-smb",
  1294. "initial-setup-gui",
  1295. "libcanberra-gtk2",
  1296. "libcanberra-gtk3",
  1297. "libproxy-mozjs",
  1298. "librsvg2",
  1299. "libsane-hpaio",
  1300. "metacity",
  1301. "mousetweaks",
  1302. "nautilus",
  1303. "nautilus-sendto",
  1304. "nm-connection-editor",
  1305. "orca",
  1306. "redhat-access-gui",
  1307. "sane-backends-drivers-scanners",
  1308. "seahorse",
  1309. "setroubleshoot",
  1310. "sushi",
  1311. "totem",
  1312. "totem-nautilus",
  1313. "vinagre",
  1314. "vino",
  1315. "xdg-user-dirs-gtk",
  1316. "yelp",
  1317. ],
  1318. "optional": [
  1319. "",
  1320. "alacarte",
  1321. "dconf-editor",
  1322. "dvgrab",
  1323. "fonts-tweak-tool",
  1324. "gconf-editor",
  1325. "gedit-plugins",
  1326. "gnote",
  1327. "libappindicator-gtk3",
  1328. "seahorse-nautilus",
  1329. "seahorse-sharing",
  1330. "vim-X11",
  1331. "xguest",
  1332. ],
  1333. "type": "package group",
  1334. }
  1335. cmd_out = """Group: GNOME
  1336. Group-Id: gnome-desktop
  1337. Description: GNOME is a highly intuitive and user friendly desktop environment.
  1338. Mandatory Packages:
  1339. =NetworkManager-libreswan-gnome
  1340. =PackageKit-command-not-found
  1341. =PackageKit-gtk3-module
  1342. abrt-desktop
  1343. =at-spi2-atk
  1344. =at-spi2-core
  1345. =avahi
  1346. =baobab
  1347. -caribou
  1348. -caribou-gtk2-module
  1349. -caribou-gtk3-module
  1350. =cheese
  1351. =chrome-gnome-shell
  1352. =compat-cheese314
  1353. =control-center
  1354. =dconf
  1355. =empathy
  1356. =eog
  1357. =evince
  1358. =evince-nautilus
  1359. =file-roller
  1360. =file-roller-nautilus
  1361. =firewall-config
  1362. =firstboot
  1363. fprintd-pam
  1364. =gdm
  1365. =gedit
  1366. =glib-networking
  1367. =gnome-bluetooth
  1368. =gnome-boxes
  1369. =gnome-calculator
  1370. =gnome-classic-session
  1371. =gnome-clocks
  1372. =gnome-color-manager
  1373. =gnome-contacts
  1374. =gnome-dictionary
  1375. =gnome-disk-utility
  1376. =gnome-font-viewer
  1377. =gnome-getting-started-docs
  1378. =gnome-icon-theme
  1379. =gnome-icon-theme-extras
  1380. =gnome-icon-theme-symbolic
  1381. =gnome-initial-setup
  1382. =gnome-packagekit
  1383. =gnome-packagekit-updater
  1384. =gnome-screenshot
  1385. =gnome-session
  1386. =gnome-session-xsession
  1387. =gnome-settings-daemon
  1388. =gnome-shell
  1389. =gnome-software
  1390. =gnome-system-log
  1391. =gnome-system-monitor
  1392. =gnome-terminal
  1393. =gnome-terminal-nautilus
  1394. =gnome-themes-standard
  1395. =gnome-tweak-tool
  1396. =gnome-user-docs
  1397. =gnome-weather
  1398. =gucharmap
  1399. =gvfs-afc
  1400. =gvfs-afp
  1401. =gvfs-archive
  1402. =gvfs-fuse
  1403. =gvfs-goa
  1404. =gvfs-gphoto2
  1405. =gvfs-mtp
  1406. =gvfs-smb
  1407. initial-setup-gui
  1408. =libcanberra-gtk2
  1409. =libcanberra-gtk3
  1410. =libproxy-mozjs
  1411. =librsvg2
  1412. =libsane-hpaio
  1413. =metacity
  1414. =mousetweaks
  1415. =nautilus
  1416. =nautilus-sendto
  1417. =nm-connection-editor
  1418. =orca
  1419. -redhat-access-gui
  1420. =sane-backends-drivers-scanners
  1421. =seahorse
  1422. =setroubleshoot
  1423. =sushi
  1424. =totem
  1425. =totem-nautilus
  1426. =vinagre
  1427. =vino
  1428. =xdg-user-dirs-gtk
  1429. =yelp
  1430. Default Packages:
  1431. =qgnomeplatform
  1432. =xdg-desktop-portal-gtk
  1433. Optional Packages:
  1434. alacarte
  1435. dconf-editor
  1436. dvgrab
  1437. fonts-tweak-tool
  1438. gconf-editor
  1439. gedit-plugins
  1440. gnote
  1441. libappindicator-gtk3
  1442. seahorse-nautilus
  1443. seahorse-sharing
  1444. vim-X11
  1445. xguest
  1446. """
  1447. with patch.dict(
  1448. yumpkg.__salt__, {"cmd.run_stdout": MagicMock(return_value=cmd_out)}
  1449. ):
  1450. info = yumpkg.group_info("@gnome-desktop")
  1451. self.assertDictEqual(info, expected)
  1452. @skipIf(pytest is None, "PyTest is missing")
  1453. class YumUtilsTestCase(TestCase, LoaderModuleMockMixin):
  1454. """
  1455. Yum/Dnf utils tests.
  1456. """
  1457. def setup_loader_modules(self):
  1458. return {
  1459. yumpkg: {
  1460. "__context__": {"yum_bin": "fake-yum"},
  1461. "__grains__": {
  1462. "osarch": "x86_64",
  1463. "os_family": "RedHat",
  1464. "osmajorrelease": 7,
  1465. },
  1466. }
  1467. }
  1468. def test_call_yum_default(self):
  1469. """
  1470. Call default Yum/Dnf.
  1471. :return:
  1472. """
  1473. with patch.dict(
  1474. yumpkg.__salt__,
  1475. {"cmd.run_all": MagicMock(), "config.get": MagicMock(return_value=False)},
  1476. ):
  1477. yumpkg._call_yum(["-y", "--do-something"]) # pylint: disable=W0106
  1478. yumpkg.__salt__["cmd.run_all"].assert_called_once_with(
  1479. ["fake-yum", "-y", "--do-something"],
  1480. env={},
  1481. output_loglevel="trace",
  1482. python_shell=False,
  1483. )
  1484. @patch("salt.utils.systemd.has_scope", MagicMock(return_value=True))
  1485. def test_call_yum_in_scope(self):
  1486. """
  1487. Call Yum/Dnf within the scope.
  1488. :return:
  1489. """
  1490. with patch.dict(
  1491. yumpkg.__salt__,
  1492. {"cmd.run_all": MagicMock(), "config.get": MagicMock(return_value=True)},
  1493. ):
  1494. yumpkg._call_yum(["-y", "--do-something"]) # pylint: disable=W0106
  1495. yumpkg.__salt__["cmd.run_all"].assert_called_once_with(
  1496. ["systemd-run", "--scope", "fake-yum", "-y", "--do-something"],
  1497. env={},
  1498. output_loglevel="trace",
  1499. python_shell=False,
  1500. )
  1501. def test_call_yum_with_kwargs(self):
  1502. """
  1503. Call Yum/Dnf with the optinal keyword arguments.
  1504. :return:
  1505. """
  1506. with patch.dict(
  1507. yumpkg.__salt__,
  1508. {"cmd.run_all": MagicMock(), "config.get": MagicMock(return_value=False)},
  1509. ):
  1510. yumpkg._call_yum(
  1511. ["-y", "--do-something"],
  1512. python_shell=True,
  1513. output_loglevel="quiet",
  1514. ignore_retcode=False,
  1515. username="Darth Vader",
  1516. ) # pylint: disable=W0106
  1517. yumpkg.__salt__["cmd.run_all"].assert_called_once_with(
  1518. ["fake-yum", "-y", "--do-something"],
  1519. env={},
  1520. ignore_retcode=False,
  1521. output_loglevel="quiet",
  1522. python_shell=True,
  1523. username="Darth Vader",
  1524. )