From 291579c02b630e453a4ec90936218964bd5c5f89 Mon Sep 17 00:00:00 2001 From: Tyler Johnson Date: Wed, 25 Sep 2019 10:39:27 -0600 Subject: [PATCH] Cherry-pick pkg test fixes from neon --- tests/integration/states/test_pkg.py | 822 ++++++++------------------- 1 file changed, 227 insertions(+), 595 deletions(-) diff --git a/tests/integration/states/test_pkg.py b/tests/integration/states/test_pkg.py index 1b87fbcf7b..a0923235b2 100644 --- a/tests/integration/states/test_pkg.py +++ b/tests/integration/states/test_pkg.py @@ -15,12 +15,11 @@ from tests.support.mixins import SaltReturnAssertsMixin from tests.support.unit import skipIf from tests.support.helpers import ( destructiveTest, - requires_system_grains, requires_salt_modules, - flaky ) # Import Salt libs +import salt.utils.files import salt.utils.path import salt.utils.pkg.rpm import salt.utils.platform @@ -28,163 +27,97 @@ import salt.utils.platform # Import 3rd-party libs from salt.ext import six from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin +try: + from distro import LinuxDistribution + pre_grains = LinuxDistribution() +except ImportError: + pre_grains = None + log = logging.getLogger(__name__) -__testcontext__ = {} +_PKG_EPOCH_TARGETS = [] +_PKG_TARGETS = ['figlet', 'sl'] +_PKG_32_TARGETS = [] +_PKG_CAP_TARGETS = [] +_PKG_DOT_TARGETS = [] +_WILDCARDS_SUPPORTED = False +_VERSION_SPEC_SUPPORTED = True -_PKG_TARGETS = { - 'Arch': ['sl', 'libpng'], - 'Debian': ['python-plist', 'apg'], - 'RedHat': ['units', 'zsh-html'], - 'FreeBSD': ['aalib', 'pth'], - 'Suse': ['aalib', 'htop'], - 'MacOS': ['libpng', 'jpeg'], - 'Windows': ['putty', '7zip'], -} - -_PKG_CAP_TARGETS = { - 'Suse': [('perl(ZNC)', 'znc-perl')], -} - -_PKG_TARGETS_32 = { - 'CentOS': 'xz-devel.i686' -} - -# Test packages with dot in pkg name -# (https://github.com/saltstack/salt/issues/8614) -_PKG_TARGETS_DOT = { - 'RedHat': {'5': 'python-migrate0.5', - '6': 'tomcat6-el-2.1-api', - '7': 'tomcat-el-2.2-api'} -} - -# Test packages with epoch in version -# (https://github.com/saltstack/salt/issues/31619) -_PKG_TARGETS_EPOCH = { - 'RedHat': {'7': 'comps-extras'}, -} - -_WILDCARDS_SUPPORTED = ('Arch', 'Debian', 'RedHat') +if salt.utils.platform.is_windows(): + _PKG_TARGETS = ['7zip', 'putty'] +if pre_grains: + if 'arch' in pre_grains.like(): + _WILDCARDS_SUPPORTED = True + elif 'debian' in pre_grains.like(): + _WILDCARDS_SUPPORTED = True + elif 'freebsd' in pre_grains.like(): + _VERSION_SPEC_SUPPORTED = False + elif 'rhel' in pre_grains.like(): + _PKG_TARGETS = ['units', 'zsh-html'] + _WILDCARDS_SUPPORTED = True + if pre_grains.id() == 'centos': + if pre_grains.major_version() == 5: + _PKG_32_TARGETS.append('xz-devel.i386') + else: + _PKG_32_TARGETS.append('xz-devel.i686') + if pre_grains.major_version() == 5: + _PKG_DOT_TARGETS.append('python-migrate0.5') + elif pre_grains.major_version() == 6: + _PKG_DOT_TARGETS.append('tomcat6-el-2.1-api') + elif pre_grains.major_version() == 7: + _PKG_DOT_TARGETS.append('tomcat-el-2.2-api') + _PKG_EPOCH_TARGETS.append('comps-extras') + elif 'sles' in pre_grains.like(): + _PKG_CAP_TARGETS.append(('perl(ZNC)', 'znc-perl')) -def pkgmgr_avail(run_function, grains): - ''' - Return True if the package manager is available for use - ''' - def proc_fd_lsof(path): - ''' - Return True if any entry in /proc/locks points to path. Example data: - - .. code-block:: bash - - # cat /proc/locks - 1: FLOCK ADVISORY WRITE 596 00:0f:10703 0 EOF - 2: FLOCK ADVISORY WRITE 14590 00:0f:11282 0 EOF - 3: POSIX ADVISORY WRITE 653 00:0f:11422 0 EOF - ''' - import glob - # https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-proc-locks.html - locks = run_function('cmd.run', ['cat /proc/locks']).splitlines() - for line in locks: - fields = line.split() - try: - major, minor, inode = fields[5].split(':') - inode = int(inode) - except (IndexError, ValueError): - return False - - for fd in glob.glob('/proc/*/fd'): - fd_path = os.path.realpath(fd) - # If the paths match and the inode is locked - if fd_path == path and os.stat(fd_path).st_ino == inode: - return True - - return False - - def get_lock(path): - ''' - Return True if any locks are found for path - ''' - # Try lsof if it's available - if salt.utils.path.which('lsof'): - lock = run_function('cmd.run', ['lsof {0}'.format(path)]) - return True if len(lock) else False - - # Try to find any locks on path from /proc/locks - elif grains.get('kernel') == 'Linux': - return proc_fd_lsof(path) - - return False - - if 'Debian' in grains.get('os_family', ''): - for path in ['/var/lib/apt/lists/lock']: - if get_lock(path): - return False - - return True - - -def latest_version(run_function, *names): - ''' - Helper function which ensures that we don't make any unnecessary calls to - pkg.latest_version to figure out what version we need to install. This - won't stop pkg.latest_version from being run in a pkg.latest state, but it - will reduce the amount of times we check the latest version here in the - test suite. - ''' - key = 'latest_version' - if key not in __testcontext__: - __testcontext__[key] = {} - targets = [x for x in names if x not in __testcontext__[key]] - if targets: - result = run_function('pkg.latest_version', targets, refresh=False) - try: - __testcontext__[key].update(result) - except ValueError: - # Only a single target, pkg.latest_version returned a string - __testcontext__[key][targets[0]] = result - - ret = dict([(x, __testcontext__[key][x]) for x in names]) - if len(names) == 1: - return ret[names[0]] - return ret - - -@flaky @destructiveTest -@requires_salt_modules('pkg.version', 'pkg.latest_version') class PkgTest(ModuleCase, SaltReturnAssertsMixin): - ''' - pkg.installed state tests - ''' - def setUp(self): - ''' - Ensure that we only refresh the first time we run a test - ''' - super(PkgTest, self).setUp() - if 'refresh' not in __testcontext__: - self.run_function('pkg.refresh_db') - __testcontext__['refresh'] = True + @classmethod + def setUpClass(cls): + cls.ctx = {} - @requires_system_grains - def test_pkg_001_installed(self, grains=None): + @classmethod + def tearDownClass(cls): + del cls.ctx + + def latest_version(self, *names): + ''' + Helper function which ensures that we don't make any unnecessary calls to + pkg.latest_version to figure out what version we need to install. This + won't stop pkg.latest_version from being run in a pkg.latest state, but it + will reduce the amount of times we check the latest version here in the + test suite. + ''' + key = 'latest_version' + if key not in self.ctx: + self.ctx[key] = dict() + targets = [x for x in names if x not in self.ctx[key]] + if targets: + result = self.run_function('pkg.latest_version', targets, refresh=False) + try: + self.ctx[key].update(result) + except ValueError: + # Only a single target, pkg.latest_version returned a string + self.ctx[key][targets[0]] = result + + ret = dict([(x, self.ctx[key].get(x, '')) for x in names]) + if len(names) == 1: + return ret[names[0]] + return ret + + def setUp(self): + super(PkgTest, self).setUp() + if 'refresh' not in self.ctx: + self.run_function('pkg.refresh_db') + self.ctx['refresh'] = True + + def test_pkg_001_installed(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] + target = _PKG_TARGETS[0] version = self.run_function('pkg.version', [target]) # If this assert fails, we need to find new targets, this test needs to @@ -197,29 +130,12 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_002_installed_with_version(self, grains=None): + @skipIf(not _VERSION_SPEC_SUPPORTED, 'Version specification not supported') + def test_pkg_002_installed_with_version(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Don't perform this test on FreeBSD since version specification is not - # supported. - if os_family == 'FreeBSD': - return - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - if os_family == 'Arch': + if pre_grains and 'arch' in pre_grains.like(): for idx in range(13): if idx == 12: raise Exception('Package database locked after 60 seconds, ' @@ -228,8 +144,8 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): break time.sleep(5) - target = pkg_targets[0] - version = latest_version(self.run_function, target) + target = _PKG_TARGETS[0] + version = self.latest_version(target) # If this assert fails, we need to find new targets, this test needs to # be able to test successful installation of packages, so this package @@ -244,65 +160,34 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_003_installed_multipkg(self, grains=None): + def test_pkg_003_installed_multipkg(self): ''' This is a destructive test as it installs and then removes two packages ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - version = self.run_function('pkg.version', pkg_targets) + version = self.run_function('pkg.version', _PKG_TARGETS) # If this assert fails, we need to find new targets, this test needs to # be able to test successful installation of packages, so these # packages need to not be installed before we run the states below - try: - self.assertFalse(any(version.values())) - except AssertionError: - self.assertSaltTrueReturn(self.run_state('pkg.removed', name=None, pkgs=pkg_targets)) + self.assertFalse(any(version.values())) + self.assertSaltTrueReturn(self.run_state('pkg.removed', name=None, pkgs=_PKG_TARGETS)) try: ret = self.run_state('pkg.installed', name=None, - pkgs=pkg_targets, + pkgs=_PKG_TARGETS, refresh=False) self.assertSaltTrueReturn(ret) finally: - ret = self.run_state('pkg.removed', name=None, pkgs=pkg_targets) + ret = self.run_state('pkg.removed', name=None, pkgs=_PKG_TARGETS) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_004_installed_multipkg_with_version(self, grains=None): + @skipIf(not _VERSION_SPEC_SUPPORTED, 'Version specification not supported') + def test_pkg_004_installed_multipkg_with_version(self): ''' This is a destructive test as it installs and then removes two packages ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Don't perform this test on FreeBSD since version specification is not - # supported. - if os_family == 'FreeBSD': - return - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(bool(pkg_targets)) - - if os_family == 'Arch': + if pre_grains and 'arch' in pre_grains.like(): for idx in range(13): if idx == 12: raise Exception('Package database locked after 60 seconds, ' @@ -311,14 +196,14 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): break time.sleep(5) - version = latest_version(self.run_function, pkg_targets[0]) + version = self.latest_version(_PKG_TARGETS[0]) # If this assert fails, we need to find new targets, this test needs to # be able to test successful installation of packages, so these # packages need to not be installed before we run the states below self.assertTrue(bool(version)) - pkgs = [{pkg_targets[0]: version}, pkg_targets[1]] + pkgs = [{_PKG_TARGETS[0]: version}, _PKG_TARGETS[1]] try: ret = self.run_state('pkg.installed', @@ -327,63 +212,45 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): refresh=False) self.assertSaltTrueReturn(ret) finally: - ret = self.run_state('pkg.removed', name=None, pkgs=pkg_targets) + ret = self.run_state('pkg.removed', name=None, pkgs=_PKG_TARGETS) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_005_installed_32bit(self, grains=None): + @skipIf(not _PKG_32_TARGETS, 'No 32 bit packages have been specified for testing') + def test_pkg_005_installed_32bit(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_name = grains.get('os', '') - target = _PKG_TARGETS_32.get(os_name, '') + target = _PKG_32_TARGETS[0] # _PKG_TARGETS_32 is only populated for platforms for which Salt has to # munge package names for 32-bit-on-x86_64 (Currently only Ubuntu and # RHEL-based). Don't actually perform this test on other platforms. - if target: - # CentOS 5 has .i386 arch designation for 32-bit pkgs - if os_name == 'CentOS' \ - and grains['osrelease'].startswith('5.'): - target = target.replace('.i686', '.i386') + version = self.run_function('pkg.version', [target]) - version = self.run_function('pkg.version', [target]) + # If this assert fails, we need to find a new target. This test + # needs to be able to test successful installation of packages, so + # the target needs to not be installed before we run the states + # below + self.assertFalse(version) - # If this assert fails, we need to find a new target. This test - # needs to be able to test successful installation of packages, so - # the target needs to not be installed before we run the states - # below - self.assertFalse(bool(version)) + ret = self.run_state('pkg.installed', + name=target, + refresh=False) + self.assertSaltTrueReturn(ret) + ret = self.run_state('pkg.removed', name=target) + self.assertSaltTrueReturn(ret) - ret = self.run_state('pkg.installed', - name=target, - refresh=False) - self.assertSaltTrueReturn(ret) - ret = self.run_state('pkg.removed', name=target) - self.assertSaltTrueReturn(ret) - - @requires_system_grains - def test_pkg_006_installed_32bit_with_version(self, grains=None): + @skipIf(not _PKG_32_TARGETS, 'No 32 bit packages have been specified for testing') + def test_pkg_006_installed_32bit_with_version(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_name = grains.get('os', '') - target = _PKG_TARGETS_32.get(os_name, '') + target = _PKG_32_TARGETS[0] # _PKG_TARGETS_32 is only populated for platforms for which Salt has to # munge package names for 32-bit-on-x86_64 (Currently only Ubuntu and # RHEL-based). Don't actually perform this test on other platforms. - if not target: - self.skipTest('No targets configured for this test') - if grains.get('os_family', '') == 'Arch': + if pre_grains and 'arch' in pre_grains.like(): for idx in range(13): if idx == 12: raise Exception('Package database locked after 60 seconds, ' @@ -392,18 +259,13 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): break time.sleep(5) - # CentOS 5 has .i386 arch designation for 32-bit pkgs - if os_name == 'CentOS' \ - and grains['osrelease'].startswith('5.'): - target = target.replace('.i686', '.i386') - - version = latest_version(self.run_function, target) + version = self.latest_version(target) # If this assert fails, we need to find a new target. This test # needs to be able to test successful installation of the package, so # the target needs to not be installed before we run the states # below - self.assertTrue(bool(version)) + self.assertTrue(version) ret = self.run_state('pkg.installed', name=target, @@ -413,26 +275,17 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_007_with_dot_in_pkgname(self, grains=None): + @skipIf(not _PKG_DOT_TARGETS, 'No packages with "." in their name have been configured for') + def test_pkg_007_with_dot_in_pkgname(self=None): ''' This tests for the regression found in the following issue: https://github.com/saltstack/salt/issues/8614 This is a destructive test as it installs a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') + target = _PKG_DOT_TARGETS[0] - os_family = grains.get('os_family', '') - os_version = grains.get('osmajorrelease') - target = _PKG_TARGETS_DOT.get(os_family, {}).get(os_version) - - if not target: - self.skipTest('No targets configured for this test') - - version = latest_version(self.run_function, target) + version = self.latest_version(target) # If this assert fails, we need to find a new target. This test # needs to be able to test successful installation of the package, so # the target needs to not be installed before we run the @@ -443,31 +296,22 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_008_epoch_in_version(self, grains=None): + @skipIf(not _PKG_EPOCH_TARGETS, 'No targets have been configured with "epoch" in the version') + def test_pkg_008_epoch_in_version(self): ''' This tests for the regression found in the following issue: https://github.com/saltstack/salt/issues/8614 This is a destructive test as it installs a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') + target = _PKG_EPOCH_TARGETS[0] - os_family = grains.get('os_family', '') - os_version = grains.get('osmajorrelease') - target = _PKG_TARGETS_EPOCH.get(os_family, {}).get(os_version) - - if not target: - self.skipTest('No targets configured for this test') - - version = latest_version(self.run_function, target) + version = self.latest_version(target) # If this assert fails, we need to find a new target. This test # needs to be able to test successful installation of the package, so # the target needs to not be installed before we run the # pkg.installed state below - self.assertTrue(bool(version)) + self.assertTrue(version) ret = self.run_state('pkg.installed', name=target, version=version, @@ -477,70 +321,32 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): self.assertSaltTrueReturn(ret) @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_009_latest_with_epoch(self, grains=None): + @requires_salt_modules('pkg.info_installed') + def test_pkg_009_latest_with_epoch(self): ''' This tests for the following issue: https://github.com/saltstack/salt/issues/31014 This is a destructive test as it installs a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - test_name = 'bash-completion' - if grains.get('os') == 'Amazon' and grains.get('osmajorrelease') != 2: - test_name = 'bash-doc' + package = 'bash-completion' + pkgquery = 'version' ret = self.run_state('pkg.installed', - name=test_name, + name=package, refresh=False) self.assertSaltTrueReturn(ret) - @requires_salt_modules('pkg.info_installed') - @requires_system_grains - def test_pkg_010_latest_with_epoch_and_info_installed(self, grains=None): - ''' - Need to check to ensure the package has been - installed after the pkg_latest_epoch sls - file has been run. This needs to be broken up into - a separate method so I can add the requires_salt_modules - decorator to only the pkg.info_installed command. - ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - package = 'bash-completion' - if grains.get('os') == 'Amazon' and grains.get('osmajorrelease') != 2: - package = 'bash-doc' - - pkgquery = 'version' - ret = self.run_function('pkg.info_installed', [package]) self.assertTrue(pkgquery in six.text_type(ret)) - @requires_system_grains - def test_pkg_011_latest(self, grains=None): + def test_pkg_010_latest(self): ''' This tests pkg.latest with a package that has no epoch (or a zero epoch). ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] - version = latest_version(self.run_function, target) + target = _PKG_TARGETS[0] + version = self.latest_version(target) # If this assert fails, we need to find new targets, this test needs to # be able to test successful installation of packages, so this package @@ -552,43 +358,26 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_012_latest_only_upgrade(self, grains=None): + @skipIf(not pre_grains or ('debian' not in pre_grains.like()), 'This test only runs on debian based distributions') + def test_pkg_011_latest_only_upgrade(self): ''' WARNING: This test will pick a package with an available upgrade (if there is one) and upgrade it to the latest version. ''' - os_family = grains.get('os_family', '') - if os_family != 'Debian': - self.skipTest('Minion is not Debian/Ubuntu') - - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] - version = latest_version(self.run_function, target) + target = _PKG_TARGETS[0] # If this assert fails, we need to find new targets, this test needs to # be able to test that the state fails when you try to run the state # with only_upgrade=True on a package which is not already installed, # so the targeted package needs to not be installed before we run the # state below. + version = self.latest_version(target) self.assertTrue(version) - ret = self.run_state('pkg.latest', name=target, refresh=False, - only_upgrade=True) + ret = self.run_state('pkg.latest', name=target, refresh=False, only_upgrade=True) self.assertSaltFalseReturn(ret) - # Now look for updates and try to run the state on a package which is - # already up-to-date. + # Now look for updates and try to run the state on a package which is already up-to-date. installed_pkgs = self.run_function('pkg.list_pkgs') updates = self.run_function('pkg.list_upgrades', refresh=False) @@ -618,32 +407,12 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): 'Package {0} is already up-to-date'.format(target) ) - @requires_system_grains - def test_pkg_013_installed_with_wildcard_version(self, grains=None): + @skipIf(not _WILDCARDS_SUPPORTED, 'Wildcards in pkg.install are not supported') + def test_pkg_012_installed_with_wildcard_version(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - - if os_family not in _WILDCARDS_SUPPORTED: - self.skipTest( - 'Wildcards only supported on {0}'.format( - ', '.join(_WILDCARDS_SUPPORTED) - ) - ) - - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] + target = _PKG_TARGETS[0] version = self.run_function('pkg.version', [target]) # If this assert fails, we need to find new targets, this test needs to @@ -687,27 +456,13 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_014_installed_with_comparison_operator(self, grains=None): + @skipIf(not pre_grains or not any(x in pre_grains.like() for x in ('debian', 'redhat')), + 'Comparison operator not specially implemented') + def test_pkg_013_installed_with_comparison_operator(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - if os_family not in ('Debian', 'RedHat'): - self.skipTest('Comparison operator not specially implemented') - - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] + target = _PKG_TARGETS[0] version = self.run_function('pkg.version', [target]) # If this assert fails, we need to find new targets, this test needs to @@ -737,25 +492,13 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_system_grains - def test_pkg_014_installed_missing_release(self, grains=None): # pylint: disable=unused-argument + @skipIf(not pre_grains or 'redhat' not in pre_grains.like(), 'Comparison operator not specially implemented') + def test_pkg_014_installed_missing_release(self): ''' Tests that a version number missing the release portion still resolves as correctly installed. For example, version 2.0.2 instead of 2.0.2-1.el7 ''' - os_family = grains.get('os_family', '') - - if os_family.lower() != 'redhat': - self.skipTest('Test only runs on RedHat OS family') - - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] + target = _PKG_TARGETS[0] version = self.run_function('pkg.version', [target]) # If this assert fails, we need to find new targets, this test needs to @@ -775,52 +518,72 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=target) self.assertSaltTrueReturn(ret) - @requires_salt_modules('pkg.group_install') - @requires_system_grains - def test_group_installed_handle_missing_package_group(self, grains=None): # pylint: disable=unused-argument + @skipIf(not pre_grains or not any(x in pre_grains.like() for x in ('debian', 'redhat')), 'Test is for debian/redhat') + @requires_salt_modules('pkg.hold', 'pkg.unhold') + def test_pkg_015_installed_held(self): ''' - Tests that a CommandExecutionError is caught and the state returns False when - the package group is missing. Before this fix, the state would stacktrace. - See Issue #35819 for bug report. + Tests that a package can be held even when the package is already installed. ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - # Group install not available message - grp_install_msg = 'pkg.group_install not available for this platform' + if pre_grains and 'redhat' in pre_grains.like(): + # If we're in the Red Hat family first we ensure that + # the yum-plugin-versionlock package is installed + ret = self.run_state( + 'pkg.installed', + name='yum-plugin-versionlock', + refresh=False, + ) + self.assertSaltTrueReturn(ret) - # Run the pkg.group_installed state with a fake package group - ret = self.run_state('pkg.group_installed', name='handle_missing_pkg_group', - skip=['foo-bar-baz']) - ret_comment = ret['pkg_|-handle_missing_pkg_group_|-handle_missing_pkg_group_|-group_installed']['comment'] + target = _PKG_TARGETS[0] - # Not all package managers support group_installed. Skip this test if not supported. - if ret_comment == grp_install_msg: - self.skipTest(grp_install_msg) + # First we ensure that the package is installed + ret = self.run_state( + 'pkg.installed', + name=target, + refresh=False, + ) + self.assertSaltTrueReturn(ret) - # Test state should return False and should have the right comment - self.assertSaltFalseReturn(ret) - self.assertEqual(ret_comment, 'An error was encountered while installing/updating group ' - '\'handle_missing_pkg_group\': Group \'handle_missing_pkg_group\' ' - 'not found.') + # Then we check that the package is now held + ret = self.run_state( + 'pkg.installed', + name=target, + hold=True, + refresh=False, + ) - @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_cap_001_installed(self, grains=None): + # changes from pkg.hold for Red Hat family are different + if pre_grains: + if 'redhat' in pre_grains.like(): + target_changes = {'new': 'hold', 'old': ''} + elif 'debian' in pre_grains.like(): + target_changes = {'new': 'hold', 'old': 'install'} + + try: + tag = 'pkg_|-{0}_|-{0}_|-installed'.format(target) + self.assertSaltTrueReturn(ret) + self.assertIn(tag, ret) + self.assertIn('changes', ret[tag]) + self.assertIn(target, ret[tag]['changes']) + self.assertEqual(ret[tag]['changes'][target], target_changes) + finally: + # Clean up, unhold package and remove + self.run_function('pkg.unhold', name=target) + ret = self.run_state('pkg.removed', name=target) + self.assertSaltTrueReturn(ret) + if pre_grains and 'redhat' in pre_grains.like(): + ret = self.run_state('pkg.removed', + name='yum-plugin-versionlock') + self.assertSaltTrueReturn(ret) + + @skipIf(not _PKG_CAP_TARGETS, 'Capability not provided') + def test_pkg_cap_001_installed(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - os_family = grains.get('os_family', '') - pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, []) - if not len(pkg_cap_targets) > 0: - self.skipTest('Capability not provided') - - target, realpkg = pkg_cap_targets[0] + target, realpkg = _PKG_CAP_TARGETS[0] version = self.run_function('pkg.version', [target]) realver = self.run_function('pkg.version', [realpkg]) @@ -839,22 +602,12 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=realpkg) self.assertSaltTrueReturn(ret) - @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_cap_002_already_installed(self, grains=None): + @skipIf(not _PKG_CAP_TARGETS, 'Capability not available') + def test_pkg_cap_002_already_installed(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, []) - if not len(pkg_cap_targets) > 0: - self.skipTest('Capability not provided') - - target, realpkg = pkg_cap_targets[0] + target, realpkg = _PKG_CAP_TARGETS[0] version = self.run_function('pkg.version', [target]) realver = self.run_function('pkg.version', [realpkg]) @@ -881,34 +634,13 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=realpkg) self.assertSaltTrueReturn(ret) - @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_cap_003_installed_multipkg_with_version(self, grains=None): + @skipIf(not _PKG_CAP_TARGETS, 'Capability not available') + @skipIf(not _VERSION_SPEC_SUPPORTED, 'Version specification not supported') + def test_pkg_cap_003_installed_multipkg_with_version(self): ''' This is a destructive test as it installs and then removes two packages ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, []) - if not len(pkg_cap_targets) > 0: - self.skipTest('Capability not provided') - pkg_targets = _PKG_TARGETS.get(os_family, []) - - # Don't perform this test on FreeBSD since version specification is not - # supported. - if os_family == 'FreeBSD': - return - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_cap_targets) - self.assertTrue(pkg_targets) - - if os_family == 'Arch': + if pre_grains and 'arch' in pre_grains.like(): for idx in range(13): if idx == 12: raise Exception('Package database locked after 60 seconds, ' @@ -917,9 +649,9 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): break time.sleep(5) - capability, realpkg = pkg_cap_targets[0] - version = latest_version(self.run_function, pkg_targets[0]) - realver = latest_version(self.run_function, realpkg) + capability, realpkg = _PKG_CAP_TARGETS[0] + version = self.latest_version(capability) + realver = self.latest_version(realpkg) # If this assert fails, we need to find new targets, this test needs to # be able to test successful installation of packages, so these @@ -928,7 +660,7 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): self.assertTrue(realver) try: - pkgs = [{pkg_targets[0]: version}, pkg_targets[1], {capability: realver}] + pkgs = [{_PKG_TARGETS[0]: version}, _PKG_TARGETS[1], {capability: realver}] ret = self.run_state('pkg.installed', name='test_pkg_cap_003_installed_multipkg_with_version-install', pkgs=pkgs, @@ -947,7 +679,7 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): pkgs=pkgs, refresh=False, resolve_capabilities=True) self.assertSaltTrueReturn(ret) - cleanup_pkgs = pkg_targets + cleanup_pkgs = _PKG_TARGETS cleanup_pkgs.append(realpkg) finally: ret = self.run_state('pkg.removed', @@ -955,23 +687,13 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): pkgs=cleanup_pkgs) self.assertSaltTrueReturn(ret) - @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_cap_004_latest(self, grains=None): + @skipIf(not _PKG_CAP_TARGETS, 'Capability not available') + def test_pkg_cap_004_latest(self): ''' This tests pkg.latest with a package that has no epoch (or a zero epoch). ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, []) - if not len(pkg_cap_targets) > 0: - self.skipTest('Capability not provided') - - target, realpkg = pkg_cap_targets[0] + target, realpkg = _PKG_CAP_TARGETS[0] version = self.run_function('pkg.version', [target]) realver = self.run_function('pkg.version', [realpkg]) @@ -994,22 +716,12 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.removed', name=realpkg) self.assertSaltTrueReturn(ret) - @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_cap_005_downloaded(self, grains=None): + @skipIf(not _PKG_CAP_TARGETS, 'Capability not available') + def test_pkg_cap_005_downloaded(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, []) - if not len(pkg_cap_targets) > 0: - self.skipTest('Capability not provided') - - target, realpkg = pkg_cap_targets[0] + target, realpkg = _PKG_CAP_TARGETS[0] version = self.run_function('pkg.version', [target]) realver = self.run_function('pkg.version', [realpkg]) @@ -1028,22 +740,12 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): ret = self.run_state('pkg.downloaded', name=target, refresh=False, resolve_capabilities=True) self.assertSaltTrueReturn(ret) - @skipIf(salt.utils.platform.is_windows(), 'minion is windows') - @requires_system_grains - def test_pkg_cap_006_uptodate(self, grains=None): + @skipIf(not _PKG_CAP_TARGETS, 'Capability not available') + def test_pkg_cap_006_uptodate(self): ''' This is a destructive test as it installs and then removes a package ''' - # Skip test if package manager not available - if not pkgmgr_avail(self.run_function, self.run_function('grains.items')): - self.skipTest('Package manager is not available') - - os_family = grains.get('os_family', '') - pkg_cap_targets = _PKG_CAP_TARGETS.get(os_family, []) - if not len(pkg_cap_targets) > 0: - self.skipTest('Capability not provided') - - target, realpkg = pkg_cap_targets[0] + target, realpkg = _PKG_CAP_TARGETS[0] version = self.run_function('pkg.version', [target]) realver = self.run_function('pkg.version', [realpkg]) @@ -1067,73 +769,3 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin): finally: ret = self.run_state('pkg.removed', name=realpkg) self.assertSaltTrueReturn(ret) - - @skipIf(True, 'WAR ROOM TEMPORARY SKIP') # needs to be rewritten to allow for dnf on Fedora 30 and RHEL 8 - @requires_salt_modules('pkg.hold', 'pkg.unhold') - @requires_system_grains - def test_pkg_015_installed_held(self, grains=None): # pylint: disable=unused-argument - ''' - Tests that a package can be held even when the package is already installed. - ''' - os_family = grains.get('os_family', '') - - if os_family.lower() != 'redhat' and os_family.lower() != 'debian': - self.skipTest('Test only runs on RedHat or Debian family') - - pkg_targets = _PKG_TARGETS.get(os_family, []) - - if os_family.lower() == 'redhat': - # If we're in the Red Hat family first we ensure that - # the yum-plugin-versionlock package is installed - ret = self.run_state( - 'pkg.installed', - name='yum-plugin-versionlock', - refresh=False, - ) - self.assertSaltTrueReturn(ret) - - # Make sure that we have targets that match the os_family. If this - # fails then the _PKG_TARGETS dict above needs to have an entry added, - # with two packages that are not installed before these tests are run - self.assertTrue(pkg_targets) - - target = pkg_targets[0] - - # First we ensure that the package is installed - ret = self.run_state( - 'pkg.installed', - name=target, - refresh=False, - ) - self.assertSaltTrueReturn(ret) - - # Then we check that the package is now held - ret = self.run_state( - 'pkg.installed', - name=target, - hold=True, - refresh=False, - ) - - # changes from pkg.hold for Red Hat family are different - if os_family.lower() == 'redhat': - target_changes = {'new': 'hold', 'old': ''} - elif os_family.lower() == 'debian': - target_changes = {'new': 'hold', 'old': 'install'} - - try: - tag = 'pkg_|-{0}_|-{0}_|-installed'.format(target) - self.assertSaltTrueReturn(ret) - self.assertIn(tag, ret) - self.assertIn('changes', ret[tag]) - self.assertIn(target, ret[tag]['changes']) - self.assertEqual(ret[tag]['changes'][target], target_changes) - finally: - # Clean up, unhold package and remove - self.run_function('pkg.unhold', name=target) - ret = self.run_state('pkg.removed', name=target) - self.assertSaltTrueReturn(ret) - if os_family.lower() == 'redhat': - ret = self.run_state('pkg.removed', - name='yum-plugin-versionlock') - self.assertSaltTrueReturn(ret)