test_pkg.py 37 KB

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