test_pkg.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. # -*- coding: utf-8 -*-
  2. """
  3. tests for pkg state
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import logging
  7. import os
  8. import time
  9. import pytest
  10. import salt.utils.files
  11. import salt.utils.path
  12. import salt.utils.pkg.rpm
  13. import salt.utils.platform
  14. from salt.ext import six
  15. from salt.ext.six.moves import range
  16. from tests.support.case import ModuleCase
  17. from tests.support.helpers import not_runs_on, requires_system_grains, runs_on
  18. from tests.support.mixins import SaltReturnAssertsMixin
  19. from tests.support.unit import skipIf
  20. log = logging.getLogger(__name__)
  21. @pytest.mark.destructive_test
  22. @pytest.mark.windows_whitelisted
  23. class PkgTest(ModuleCase, SaltReturnAssertsMixin):
  24. _PKG_EPOCH_TARGETS = []
  25. _PKG_32_TARGETS = []
  26. _PKG_CAP_TARGETS = []
  27. _PKG_DOT_TARGETS = []
  28. _WILDCARDS_SUPPORTED = False
  29. _VERSION_SPEC_SUPPORTED = True
  30. @classmethod
  31. @requires_system_grains
  32. def setUpClass(cls, grains=None): # pylint:disable=W0221
  33. cls.ctx = {}
  34. cls._PKG_TARGETS = ["figlet", "sl"]
  35. if grains["os"] == "Windows":
  36. cls._PKG_TARGETS = ["7zip", "putty"]
  37. elif grains["os"] == "freebsd":
  38. cls._VERSION_SPEC_SUPPORTED = False
  39. elif grains["os_family"] in ("Arch", "Debian"):
  40. cls._WILDCARDS_SUPPORTED = True
  41. elif grains["os"] == "Amazon":
  42. cls._PKG_TARGETS = ["lynx", "gnuplot"]
  43. elif grains["os_family"] == "RedHat":
  44. cls._PKG_TARGETS = ["units", "zsh-html"]
  45. cls._WILDCARDS_SUPPORTED = True
  46. if grains["os"] == "CentOS":
  47. if grains["osmajorrelease"] == 5:
  48. cls._PKG_32_TARGETS = ["xz-devel.i386"]
  49. else:
  50. cls._PKG_32_TARGETS.append("xz-devel.i686")
  51. if grains["osmajorrelease"] == 5:
  52. cls._PKG_DOT_TARGETS = ["python-migrate0.5"]
  53. elif grains["osmajorrelease"] == 6:
  54. cls._PKG_DOT_TARGETS = ["tomcat6-el-2.1-api"]
  55. elif grains["osmajorrelease"] == 7:
  56. cls._PKG_DOT_TARGETS = ["tomcat-el-2.2-api"]
  57. cls._PKG_EPOCH_TARGETS = ["comps-extras"]
  58. elif grains["osmajorrelease"] == 8:
  59. cls._PKG_DOT_TARGETS = ["vid.stab"]
  60. cls._PKG_EPOCH_TARGETS = ["traceroute"]
  61. elif grains["os_family"] == "Suse":
  62. cls._PKG_TARGETS = ["lynx", "htop"]
  63. if grains["os"] == "SUSE":
  64. cls._PKG_CAP_TARGETS = [("perl(ZNC)", "znc-perl")]
  65. @classmethod
  66. def tearDownClass(cls):
  67. del cls.ctx
  68. def latest_version(self, *names):
  69. """
  70. Helper function which ensures that we don't make any unnecessary calls to
  71. pkg.latest_version to figure out what version we need to install. This
  72. won't stop pkg.latest_version from being run in a pkg.latest state, but it
  73. will reduce the amount of times we check the latest version here in the
  74. test suite.
  75. """
  76. key = "latest_version"
  77. if key not in self.ctx:
  78. self.ctx[key] = dict()
  79. targets = [x for x in names if x not in self.ctx[key]]
  80. if targets:
  81. result = self.run_function("pkg.latest_version", targets, refresh=False)
  82. try:
  83. self.ctx[key].update(result)
  84. except ValueError:
  85. # Only a single target, pkg.latest_version returned a string
  86. self.ctx[key][targets[0]] = result
  87. ret = dict([(x, self.ctx[key].get(x, "")) for x in names])
  88. if len(names) == 1:
  89. return ret[names[0]]
  90. return ret
  91. @requires_system_grains
  92. def setUp(self, grains=None): # pylint:disable=W0221
  93. super(PkgTest, self).setUp()
  94. if "refresh" not in self.ctx:
  95. self.run_function("pkg.refresh_db")
  96. self.ctx["refresh"] = True
  97. # If this is Arch Linux, check if pacman is in use by another process
  98. if grains["os_family"] == "Arch":
  99. for _ in range(12):
  100. if not os.path.isfile("/var/lib/pacman/db.lck"):
  101. break
  102. else:
  103. time.sleep(5)
  104. else:
  105. raise Exception("Package database locked after 60 seconds, bailing out")
  106. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  107. @pytest.mark.requires_salt_modules("pkg.version")
  108. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  109. def test_pkg_001_installed(self):
  110. """
  111. This is a destructive test as it installs and then removes a package
  112. """
  113. target = self._PKG_TARGETS[0]
  114. version = self.run_function("pkg.version", [target])
  115. # If this assert fails, we need to find new targets, this test needs to
  116. # be able to test successful installation of packages, so this package
  117. # needs to not be installed before we run the states below
  118. self.assertFalse(version)
  119. ret = self.run_state("pkg.installed", name=target, refresh=False)
  120. self.assertSaltTrueReturn(ret)
  121. ret = self.run_state("pkg.removed", name=target)
  122. self.assertSaltTrueReturn(ret)
  123. @skipIf(not _VERSION_SPEC_SUPPORTED, "Version specification not supported")
  124. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  125. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  126. def test_pkg_002_installed_with_version(self):
  127. """
  128. This is a destructive test as it installs and then removes a package
  129. """
  130. if not self._VERSION_SPEC_SUPPORTED:
  131. self.skipTest("Version specification not supported")
  132. target = self._PKG_TARGETS[0]
  133. version = self.latest_version(target)
  134. # If this assert fails, we need to find new targets, this test needs to
  135. # be able to test successful installation of packages, so this package
  136. # needs to not be installed before we run the states below
  137. self.assertTrue(version)
  138. ret = self.run_state(
  139. "pkg.installed", name=target, version=version, refresh=False
  140. )
  141. self.assertSaltTrueReturn(ret)
  142. ret = self.run_state("pkg.removed", name=target)
  143. self.assertSaltTrueReturn(ret)
  144. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  145. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  146. def test_pkg_003_installed_multipkg(self):
  147. """
  148. This is a destructive test as it installs and then removes two packages
  149. """
  150. version = self.run_function("pkg.version", self._PKG_TARGETS)
  151. # If this assert fails, we need to find new targets, this test needs to
  152. # be able to test successful installation of packages, so these
  153. # packages need to not be installed before we run the states below
  154. self.assertFalse(any(version.values()))
  155. self.assertSaltTrueReturn(
  156. self.run_state("pkg.removed", name=None, pkgs=self._PKG_TARGETS)
  157. )
  158. try:
  159. ret = self.run_state(
  160. "pkg.installed", name=None, pkgs=self._PKG_TARGETS, refresh=False
  161. )
  162. self.assertSaltTrueReturn(ret)
  163. finally:
  164. ret = self.run_state("pkg.removed", name=None, pkgs=self._PKG_TARGETS)
  165. self.assertSaltTrueReturn(ret)
  166. @skipIf(not _VERSION_SPEC_SUPPORTED, "Version specification not supported")
  167. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  168. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  169. def test_pkg_004_installed_multipkg_with_version(self):
  170. """
  171. This is a destructive test as it installs and then removes two packages
  172. """
  173. if not self._VERSION_SPEC_SUPPORTED:
  174. self.skipTest("Version specification not supported")
  175. version = self.latest_version(self._PKG_TARGETS[0])
  176. # If this assert fails, we need to find new targets, this test needs to
  177. # be able to test successful installation of packages, so these
  178. # packages need to not be installed before we run the states below
  179. self.assertTrue(bool(version))
  180. pkgs = [{self._PKG_TARGETS[0]: version}, self._PKG_TARGETS[1]]
  181. try:
  182. ret = self.run_state("pkg.installed", name=None, pkgs=pkgs, refresh=False)
  183. self.assertSaltTrueReturn(ret)
  184. finally:
  185. ret = self.run_state("pkg.removed", name=None, pkgs=self._PKG_TARGETS)
  186. self.assertSaltTrueReturn(ret)
  187. @skipIf(not _PKG_32_TARGETS, "No 32 bit packages have been specified for testing")
  188. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  189. @pytest.mark.requires_salt_modules("pkg.version")
  190. def test_pkg_005_installed_32bit(self):
  191. """
  192. This is a destructive test as it installs and then removes a package
  193. """
  194. if not self._PKG_32_TARGETS:
  195. self.skipTest("No 32 bit packages have been specified for testing")
  196. target = self._PKG_32_TARGETS[0]
  197. # _PKG_TARGETS_32 is only populated for platforms for which Salt has to
  198. # munge package names for 32-bit-on-x86_64 (Currently only Ubuntu and
  199. # RHEL-based). Don't actually perform this test on other platforms.
  200. version = self.run_function("pkg.version", [target])
  201. # If this assert fails, we need to find a new target. This test
  202. # needs to be able to test successful installation of packages, so
  203. # the target needs to not be installed before we run the states
  204. # below
  205. self.assertFalse(version)
  206. ret = self.run_state("pkg.installed", name=target, refresh=False)
  207. self.assertSaltTrueReturn(ret)
  208. ret = self.run_state("pkg.removed", name=target)
  209. self.assertSaltTrueReturn(ret)
  210. @skipIf(not _PKG_32_TARGETS, "No 32 bit packages have been specified for testing")
  211. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  212. def test_pkg_006_installed_32bit_with_version(self):
  213. """
  214. This is a destructive test as it installs and then removes a package
  215. """
  216. if not self._PKG_32_TARGETS:
  217. self.skipTest("No 32 bit packages have been specified for testing")
  218. target = self._PKG_32_TARGETS[0]
  219. # _PKG_TARGETS_32 is only populated for platforms for which Salt has to
  220. # munge package names for 32-bit-on-x86_64 (Currently only Ubuntu and
  221. # RHEL-based). Don't actually perform this test on other platforms.
  222. version = self.latest_version(target)
  223. # If this assert fails, we need to find a new target. This test
  224. # needs to be able to test successful installation of the package, so
  225. # the target needs to not be installed before we run the states
  226. # below
  227. self.assertTrue(version)
  228. ret = self.run_state(
  229. "pkg.installed", name=target, version=version, refresh=False
  230. )
  231. self.assertSaltTrueReturn(ret)
  232. ret = self.run_state("pkg.removed", name=target)
  233. self.assertSaltTrueReturn(ret)
  234. @skipIf(
  235. not _PKG_DOT_TARGETS,
  236. 'No packages with "." in their name have been configured for',
  237. )
  238. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  239. def test_pkg_007_with_dot_in_pkgname(self=None):
  240. """
  241. This tests for the regression found in the following issue:
  242. https://github.com/saltstack/salt/issues/8614
  243. This is a destructive test as it installs a package
  244. """
  245. if not self._PKG_DOT_TARGETS:
  246. self.skipTest('No packages with "." in their name have been specified',)
  247. target = self._PKG_DOT_TARGETS[0]
  248. version = self.latest_version(target)
  249. # If this assert fails, we need to find a new target. This test
  250. # needs to be able to test successful installation of the package, so
  251. # the target needs to not be installed before we run the
  252. # pkg.installed state below
  253. self.assertTrue(bool(version))
  254. ret = self.run_state("pkg.installed", name=target, refresh=False)
  255. self.assertSaltTrueReturn(ret)
  256. ret = self.run_state("pkg.removed", name=target)
  257. self.assertSaltTrueReturn(ret)
  258. @skipIf(
  259. not _PKG_EPOCH_TARGETS,
  260. 'No targets have been configured with "epoch" in the version',
  261. )
  262. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  263. def test_pkg_008_epoch_in_version(self):
  264. """
  265. This tests for the regression found in the following issue:
  266. https://github.com/saltstack/salt/issues/8614
  267. This is a destructive test as it installs a package
  268. """
  269. if not self._PKG_EPOCH_TARGETS:
  270. self.skipTest('No targets have been configured with "epoch" in the version')
  271. target = self._PKG_EPOCH_TARGETS[0]
  272. version = self.latest_version(target)
  273. # If this assert fails, we need to find a new target. This test
  274. # needs to be able to test successful installation of the package, so
  275. # the target needs to not be installed before we run the
  276. # pkg.installed state below
  277. self.assertTrue(version)
  278. ret = self.run_state(
  279. "pkg.installed", name=target, version=version, refresh=False
  280. )
  281. self.assertSaltTrueReturn(ret)
  282. ret = self.run_state("pkg.removed", name=target)
  283. self.assertSaltTrueReturn(ret)
  284. @runs_on(kernel="linux")
  285. @not_runs_on(os="Amazon")
  286. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  287. @pytest.mark.requires_salt_modules("pkg.version", "pkg.info_installed")
  288. @pytest.mark.slow_test(seconds=60) # Test takes >30 and <=60 seconds
  289. def test_pkg_009_latest_with_epoch(self):
  290. """
  291. This tests for the following issue:
  292. https://github.com/saltstack/salt/issues/31014
  293. This is a destructive test as it installs a package
  294. """
  295. package = "bash-completion"
  296. pkgquery = "version"
  297. ret = self.run_state("pkg.installed", name=package, refresh=False)
  298. self.assertSaltTrueReturn(ret)
  299. ret = self.run_function("pkg.info_installed", [package])
  300. self.assertTrue(pkgquery in six.text_type(ret))
  301. @pytest.mark.requires_salt_states("pkg.latest", "pkg.removed")
  302. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  303. def test_pkg_010_latest(self):
  304. """
  305. This tests pkg.latest with a package that has no epoch (or a zero
  306. epoch).
  307. """
  308. target = self._PKG_TARGETS[0]
  309. version = self.latest_version(target)
  310. # If this assert fails, we need to find new targets, this test needs to
  311. # be able to test successful installation of packages, so this package
  312. # needs to not be installed before we run the states below
  313. self.assertTrue(version)
  314. ret = self.run_state("pkg.latest", name=target, refresh=False)
  315. self.assertSaltTrueReturn(ret)
  316. ret = self.run_state("pkg.removed", name=target)
  317. self.assertSaltTrueReturn(ret)
  318. @pytest.mark.requires_salt_states("pkg.latest")
  319. @runs_on(kernel="linux", os_family="Debian")
  320. @pytest.mark.requires_salt_modules(
  321. "pkg.list_pkgs", "pkg.list_upgrades", "pkg.version"
  322. )
  323. @pytest.mark.slow_test(seconds=30) # Test takes >10 and <=30 seconds
  324. def test_pkg_011_latest_only_upgrade(self):
  325. """
  326. WARNING: This test will pick a package with an available upgrade (if
  327. there is one) and upgrade it to the latest version.
  328. """
  329. target = self._PKG_TARGETS[0]
  330. # If this assert fails, we need to find new targets, this test needs to
  331. # be able to test that the state fails when you try to run the state
  332. # with only_upgrade=True on a package which is not already installed,
  333. # so the targeted package needs to not be installed before we run the
  334. # state below.
  335. version = self.latest_version(target)
  336. self.assertTrue(version)
  337. ret = self.run_state(
  338. "pkg.latest", name=target, refresh=False, only_upgrade=True
  339. )
  340. self.assertSaltFalseReturn(ret)
  341. # Now look for updates and try to run the state on a package which is already up-to-date.
  342. installed_pkgs = self.run_function("pkg.list_pkgs")
  343. updates = self.run_function("pkg.list_upgrades", refresh=False)
  344. for pkgname in updates:
  345. if pkgname in installed_pkgs:
  346. target = pkgname
  347. break
  348. else:
  349. target = ""
  350. log.warning(
  351. "No available upgrades to installed packages, skipping "
  352. "only_upgrade=True test with already-installed package. For "
  353. "best results run this test on a machine with upgrades "
  354. "available."
  355. )
  356. if target:
  357. ret = self.run_state(
  358. "pkg.latest", name=target, refresh=False, only_upgrade=True
  359. )
  360. self.assertSaltTrueReturn(ret)
  361. new_version = self.run_function("pkg.version", [target])
  362. self.assertEqual(new_version, updates[target])
  363. ret = self.run_state(
  364. "pkg.latest", name=target, refresh=False, only_upgrade=True
  365. )
  366. self.assertEqual(
  367. ret["pkg_|-{0}_|-{0}_|-latest".format(target)]["comment"],
  368. "Package {0} is already up-to-date".format(target),
  369. )
  370. @skipIf(not _WILDCARDS_SUPPORTED, "Wildcards in pkg.install are not supported")
  371. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  372. @pytest.mark.requires_salt_modules("pkg.version")
  373. def test_pkg_012_installed_with_wildcard_version(self):
  374. """
  375. This is a destructive test as it installs and then removes a package
  376. """
  377. if not self._WILDCARDS_SUPPORTED:
  378. self.skipTest("Wildcards in pkg.install are not supported")
  379. target = self._PKG_TARGETS[0]
  380. version = self.run_function("pkg.version", [target])
  381. # If this assert fails, we need to find new targets, this test needs to
  382. # be able to test successful installation of packages, so this package
  383. # needs to not be installed before we run the states below
  384. self.assertFalse(version)
  385. ret = self.run_state("pkg.installed", name=target, version="*", refresh=False,)
  386. self.assertSaltTrueReturn(ret)
  387. # Repeat state, should pass
  388. ret = self.run_state("pkg.installed", name=target, version="*", refresh=False,)
  389. expected_comment = (
  390. "All specified packages are already installed and are at the "
  391. "desired version"
  392. )
  393. self.assertSaltTrueReturn(ret)
  394. self.assertEqual(ret[next(iter(ret))]["comment"], expected_comment)
  395. # Repeat one more time with unavailable version, test should fail
  396. ret = self.run_state(
  397. "pkg.installed", name=target, version="93413*", refresh=False,
  398. )
  399. self.assertSaltFalseReturn(ret)
  400. # Clean up
  401. ret = self.run_state("pkg.removed", name=target)
  402. self.assertSaltTrueReturn(ret)
  403. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  404. @pytest.mark.requires_salt_modules("pkg.version", "pkg.latest_version")
  405. @runs_on(kernel="linux", os_family=["Debian", "RedHat"])
  406. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  407. def test_pkg_013_installed_with_comparison_operator(self):
  408. """
  409. This is a destructive test as it installs and then removes a package
  410. """
  411. target = self._PKG_TARGETS[0]
  412. version = self.run_function("pkg.version", [target])
  413. # If this assert fails, we need to find new targets, this test needs to
  414. # be able to test successful installation of packages, so this package
  415. # needs to not be installed before we run the states below
  416. self.assertFalse(version)
  417. latest_version = self.run_function(
  418. "pkg.latest_version", [target], refresh=False
  419. )
  420. try:
  421. ret = self.run_state(
  422. "pkg.installed", name=target, version="<9999999", refresh=False,
  423. )
  424. self.assertSaltTrueReturn(ret)
  425. # The version that was installed should be the latest available
  426. version = self.run_function("pkg.version", [target])
  427. self.assertTrue(version, latest_version)
  428. finally:
  429. # Clean up
  430. ret = self.run_state("pkg.removed", name=target)
  431. self.assertSaltTrueReturn(ret)
  432. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  433. @pytest.mark.requires_salt_modules("pkg.version")
  434. @runs_on(kernel="linux", os_familiy="RedHat")
  435. def test_pkg_014_installed_missing_release(self):
  436. """
  437. Tests that a version number missing the release portion still resolves
  438. as correctly installed. For example, version 2.0.2 instead of 2.0.2-1.el7
  439. """
  440. target = self._PKG_TARGETS[0]
  441. version = self.run_function("pkg.version", [target])
  442. # If this assert fails, we need to find new targets, this test needs to
  443. # be able to test successful installation of packages, so this package
  444. # needs to not be installed before we run the states below
  445. self.assertFalse(version)
  446. ret = self.run_state(
  447. "pkg.installed",
  448. name=target,
  449. version=salt.utils.pkg.rpm.version_to_evr(version)[1],
  450. refresh=False,
  451. )
  452. self.assertSaltTrueReturn(ret)
  453. # Clean up
  454. ret = self.run_state("pkg.removed", name=target)
  455. self.assertSaltTrueReturn(ret)
  456. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  457. @pytest.mark.requires_salt_modules(
  458. "pkg.hold", "pkg.unhold", "pkg.version", "pkg.list_pkgs"
  459. )
  460. @requires_system_grains
  461. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  462. def test_pkg_015_installed_held(self, grains=None):
  463. """
  464. Tests that a package can be held even when the package is already installed.
  465. """
  466. versionlock_pkg = None
  467. if grains["os_family"] == "RedHat":
  468. pkgs = {
  469. p for p in self.run_function("pkg.list_pkgs") if "-versionlock" in p
  470. }
  471. if not pkgs:
  472. self.skipTest("No versionlock package found in repositories")
  473. for versionlock_pkg in pkgs:
  474. ret = self.run_state(
  475. "pkg.installed", name=versionlock_pkg, refresh=False
  476. )
  477. # Exit loop if a versionlock package installed correctly
  478. try:
  479. self.assertSaltTrueReturn(ret)
  480. log.debug(
  481. "Installed versionlock package: {}".format(versionlock_pkg)
  482. )
  483. break
  484. except AssertionError as e:
  485. log.debug("Versionlock package not found:\n{}".format(e))
  486. else:
  487. self.fail("Could not install versionlock package from {}".format(pkgs))
  488. target = self._PKG_TARGETS[0]
  489. # First we ensure that the package is installed
  490. ret = self.run_state("pkg.installed", name=target, refresh=False,)
  491. self.assertSaltTrueReturn(ret)
  492. # Then we check that the package is now held
  493. ret = self.run_state("pkg.installed", name=target, hold=True, refresh=False,)
  494. if versionlock_pkg and "-versionlock is not installed" in str(ret):
  495. self.skipTest("{} `{}` is installed".format(ret, versionlock_pkg))
  496. # changes from pkg.hold for Red Hat family are different
  497. target_changes = {}
  498. if grains["os_family"] == "RedHat":
  499. target_changes = {"new": "hold", "old": ""}
  500. elif grains["os_family"] == "Debian":
  501. target_changes = {"new": "hold", "old": "install"}
  502. try:
  503. tag = "pkg_|-{0}_|-{0}_|-installed".format(target)
  504. self.assertSaltTrueReturn(ret)
  505. self.assertIn(tag, ret)
  506. self.assertIn("changes", ret[tag])
  507. self.assertIn(target, ret[tag]["changes"])
  508. if not target_changes:
  509. self.skipTest(
  510. "Test needs to be configured for {}: {}".format(
  511. grains["os"], ret[tag]["changes"][target]
  512. )
  513. )
  514. self.assertEqual(ret[tag]["changes"][target], target_changes)
  515. finally:
  516. # Clean up, unhold package and remove
  517. self.run_function("pkg.unhold", name=target)
  518. ret = self.run_state("pkg.removed", name=target)
  519. self.assertSaltTrueReturn(ret)
  520. if versionlock_pkg:
  521. ret = self.run_state("pkg.removed", name=versionlock_pkg)
  522. self.assertSaltTrueReturn(ret)
  523. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  524. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  525. def test_pkg_016_conditionally_ignore_epoch(self):
  526. """
  527. See
  528. https://github.com/saltstack/salt/issues/56654#issuecomment-615034952
  529. This is a destructive test as it installs a package
  530. """
  531. if not self._PKG_EPOCH_TARGETS:
  532. self.skipTest('No targets have been configured with "epoch" in the version')
  533. target = self._PKG_EPOCH_TARGETS[0]
  534. # Strip the epoch from the latest available version
  535. version = self.latest_version(target).split(":", 1)[-1]
  536. # If this assert fails, we need to find a new target. This test
  537. # needs to be able to test successful installation of the package, so
  538. # the target needs to not be installed before we run the
  539. # pkg.installed state below
  540. self.assertTrue(version)
  541. # CASE 1: package name passed in "name" param
  542. ret = self.run_state(
  543. "pkg.installed", name=target, version=version, refresh=False
  544. )
  545. self.assertSaltTrueReturn(ret)
  546. ret = self.run_state("pkg.removed", name=target)
  547. self.assertSaltTrueReturn(ret)
  548. # CASE 2: same as case 1 but with "pkgs"
  549. ret = self.run_state(
  550. "pkg.installed", name="foo", pkgs=[{target: version}], refresh=False
  551. )
  552. self.assertSaltTrueReturn(ret)
  553. ret = self.run_state("pkg.removed", name=target)
  554. self.assertSaltTrueReturn(ret)
  555. @skipIf(not _PKG_CAP_TARGETS, "Capability not provided")
  556. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  557. @pytest.mark.requires_salt_modules("pkg.version")
  558. def test_pkg_cap_001_installed(self):
  559. """
  560. This is a destructive test as it installs and then removes a package
  561. """
  562. if not self._PKG_CAP_TARGETS:
  563. self.skipTest("Capability not provided")
  564. target, realpkg = self._PKG_CAP_TARGETS[0]
  565. version = self.run_function("pkg.version", [target])
  566. realver = self.run_function("pkg.version", [realpkg])
  567. # If this condition is False, we need to find new targets.
  568. # This needs to be able to test successful installation of packages.
  569. # These packages need to not be installed before we run the states below
  570. if not (version and realver):
  571. self.skipTest("TODO: New pkg cap targets required")
  572. try:
  573. ret = self.run_state(
  574. "pkg.installed",
  575. name=target,
  576. refresh=False,
  577. resolve_capabilities=True,
  578. test=True,
  579. )
  580. self.assertInSaltComment(
  581. "The following packages would be installed/updated: {0}".format(
  582. realpkg
  583. ),
  584. ret,
  585. )
  586. ret = self.run_state(
  587. "pkg.installed", name=target, refresh=False, resolve_capabilities=True
  588. )
  589. self.assertSaltTrueReturn(ret)
  590. finally:
  591. ret = self.run_state("pkg.removed", name=realpkg)
  592. self.assertSaltTrueReturn(ret)
  593. @skipIf(not _PKG_CAP_TARGETS, "Capability not available")
  594. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  595. def test_pkg_cap_002_already_installed(self):
  596. """
  597. This is a destructive test as it installs and then removes a package
  598. """
  599. if not self._PKG_CAP_TARGETS:
  600. self.skipTest("Capability not provided")
  601. target, realpkg = self._PKG_CAP_TARGETS[0]
  602. version = self.run_function("pkg.version", [target])
  603. realver = self.run_function("pkg.version", [realpkg])
  604. # If this condition is False, we need to find new targets.
  605. # This needs to be able to test successful installation of packages.
  606. # These packages need to not be installed before we run the states below
  607. if not (version and realver):
  608. self.skipTest("TODO: New pkg cap targets required")
  609. try:
  610. # install the package
  611. ret = self.run_state("pkg.installed", name=realpkg, refresh=False)
  612. self.assertSaltTrueReturn(ret)
  613. # Try to install again. Nothing should be installed this time.
  614. ret = self.run_state(
  615. "pkg.installed",
  616. name=target,
  617. refresh=False,
  618. resolve_capabilities=True,
  619. test=True,
  620. )
  621. self.assertInSaltComment(
  622. "All specified packages are already installed", ret
  623. )
  624. ret = self.run_state(
  625. "pkg.installed", name=target, refresh=False, resolve_capabilities=True
  626. )
  627. self.assertSaltTrueReturn(ret)
  628. self.assertInSaltComment("packages are already installed", ret)
  629. finally:
  630. ret = self.run_state("pkg.removed", name=realpkg)
  631. self.assertSaltTrueReturn(ret)
  632. @skipIf(not _PKG_CAP_TARGETS, "Capability not available")
  633. @skipIf(not _VERSION_SPEC_SUPPORTED, "Version specification not supported")
  634. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed")
  635. def test_pkg_cap_003_installed_multipkg_with_version(self):
  636. """
  637. This is a destructive test as it installs and then removes two packages
  638. """
  639. if not self._PKG_CAP_TARGETS:
  640. self.skipTest("Capability not provided")
  641. if not self._VERSION_SPEC_SUPPORTED:
  642. self.skipTest("Version specification not supported")
  643. target, realpkg = self._PKG_CAP_TARGETS[0]
  644. version = self.latest_version(target)
  645. realver = self.latest_version(realpkg)
  646. # If this condition is False, we need to find new targets.
  647. # This needs to be able to test successful installation of packages.
  648. # These packages need to not be installed before we run the states below
  649. if not (version and realver):
  650. self.skipTest("TODO: New pkg cap targets required")
  651. cleanup_pkgs = self._PKG_TARGETS
  652. try:
  653. pkgs = [
  654. {self._PKG_TARGETS[0]: version},
  655. self._PKG_TARGETS[1],
  656. {target: realver},
  657. ]
  658. ret = self.run_state(
  659. "pkg.installed",
  660. name="test_pkg_cap_003_installed_multipkg_with_version-install",
  661. pkgs=pkgs,
  662. refresh=False,
  663. )
  664. self.assertSaltFalseReturn(ret)
  665. ret = self.run_state(
  666. "pkg.installed",
  667. name="test_pkg_cap_003_installed_multipkg_with_version-install-capability",
  668. pkgs=pkgs,
  669. refresh=False,
  670. resolve_capabilities=True,
  671. test=True,
  672. )
  673. self.assertInSaltComment("packages would be installed/updated", ret)
  674. self.assertInSaltComment("{0}={1}".format(realpkg, realver), ret)
  675. ret = self.run_state(
  676. "pkg.installed",
  677. name="test_pkg_cap_003_installed_multipkg_with_version-install-capability",
  678. pkgs=pkgs,
  679. refresh=False,
  680. resolve_capabilities=True,
  681. )
  682. self.assertSaltTrueReturn(ret)
  683. cleanup_pkgs.append(realpkg)
  684. finally:
  685. ret = self.run_state(
  686. "pkg.removed",
  687. name="test_pkg_cap_003_installed_multipkg_with_version-remove",
  688. pkgs=cleanup_pkgs,
  689. )
  690. self.assertSaltTrueReturn(ret)
  691. @skipIf(not _PKG_CAP_TARGETS, "Capability not available")
  692. @pytest.mark.requires_salt_states("pkg.latest", "pkg.removed")
  693. @pytest.mark.requires_salt_modules("pkg.version")
  694. def test_pkg_cap_004_latest(self):
  695. """
  696. This tests pkg.latest with a package that has no epoch (or a zero
  697. epoch).
  698. """
  699. if not self._PKG_CAP_TARGETS:
  700. self.skipTest("Capability not provided")
  701. target, realpkg = self._PKG_CAP_TARGETS[0]
  702. version = self.run_function("pkg.version", [target])
  703. realver = self.run_function("pkg.version", [realpkg])
  704. # If this condition is False, we need to find new targets.
  705. # This needs to be able to test successful installation of packages.
  706. # These packages need to not be installed before we run the states below
  707. if not (version and realver):
  708. self.skipTest("TODO: New pkg cap targets required")
  709. try:
  710. ret = self.run_state(
  711. "pkg.latest",
  712. name=target,
  713. refresh=False,
  714. resolve_capabilities=True,
  715. test=True,
  716. )
  717. self.assertInSaltComment(
  718. "The following packages would be installed/upgraded: {0}".format(
  719. realpkg
  720. ),
  721. ret,
  722. )
  723. ret = self.run_state(
  724. "pkg.latest", name=target, refresh=False, resolve_capabilities=True
  725. )
  726. self.assertSaltTrueReturn(ret)
  727. ret = self.run_state(
  728. "pkg.latest", name=target, refresh=False, resolve_capabilities=True
  729. )
  730. self.assertSaltTrueReturn(ret)
  731. self.assertInSaltComment("is already up-to-date", ret)
  732. finally:
  733. ret = self.run_state("pkg.removed", name=realpkg)
  734. self.assertSaltTrueReturn(ret)
  735. @skipIf(not _PKG_CAP_TARGETS, "Capability not available")
  736. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed", "pkg.downloaded")
  737. @pytest.mark.requires_salt_modules("pkg.version")
  738. def test_pkg_cap_005_downloaded(self):
  739. """
  740. This is a destructive test as it installs and then removes a package
  741. """
  742. if not self._PKG_CAP_TARGETS:
  743. self.skipTest("Capability not provided")
  744. target, realpkg = self._PKG_CAP_TARGETS[0]
  745. version = self.run_function("pkg.version", [target])
  746. realver = self.run_function("pkg.version", [realpkg])
  747. # If this condition is False, we need to find new targets.
  748. # This needs to be able to test successful installation of packages.
  749. # These packages need to not be installed before we run the states below
  750. if not (version and realver):
  751. self.skipTest("TODO: New pkg cap targets required")
  752. ret = self.run_state("pkg.downloaded", name=target, refresh=False)
  753. self.assertSaltFalseReturn(ret)
  754. ret = self.run_state(
  755. "pkg.downloaded",
  756. name=target,
  757. refresh=False,
  758. resolve_capabilities=True,
  759. test=True,
  760. )
  761. self.assertInSaltComment(
  762. "The following packages would be downloaded: {0}".format(realpkg), ret
  763. )
  764. ret = self.run_state(
  765. "pkg.downloaded", name=target, refresh=False, resolve_capabilities=True
  766. )
  767. self.assertSaltTrueReturn(ret)
  768. @skipIf(not _PKG_CAP_TARGETS, "Capability not available")
  769. @pytest.mark.requires_salt_states("pkg.installed", "pkg.removed", "pkg.uptodate")
  770. @pytest.mark.requires_salt_modules("pkg.version")
  771. def test_pkg_cap_006_uptodate(self):
  772. """
  773. This is a destructive test as it installs and then removes a package
  774. """
  775. if not self._PKG_CAP_TARGETS:
  776. self.skipTest("Capability not provided")
  777. target, realpkg = self._PKG_CAP_TARGETS[0]
  778. version = self.run_function("pkg.version", [target])
  779. realver = self.run_function("pkg.version", [realpkg])
  780. # If this condition is False, we need to find new targets.
  781. # This needs to be able to test successful installation of packages.
  782. # These packages need to not be installed before we run the states below
  783. if not (version and realver):
  784. self.skipTest("TODO: New pkg cap targets required")
  785. try:
  786. ret = self.run_state(
  787. "pkg.installed", name=target, refresh=False, resolve_capabilities=True
  788. )
  789. self.assertSaltTrueReturn(ret)
  790. ret = self.run_state(
  791. "pkg.uptodate",
  792. name="test_pkg_cap_006_uptodate",
  793. pkgs=[target],
  794. refresh=False,
  795. resolve_capabilities=True,
  796. )
  797. self.assertSaltTrueReturn(ret)
  798. self.assertInSaltComment("System is already up-to-date", ret)
  799. finally:
  800. ret = self.run_state("pkg.removed", name=realpkg)
  801. self.assertSaltTrueReturn(ret)