Fixing a situation when a package is already installed via salt or manually and a state attempts to set that package to be held. Previously the holding/unholding logic was only being run against packages that were being installed. This change moves the holding logic outside and runs it against all desired packages. Adding a new test to test holding logic.

This commit is contained in:
Gareth J. Greenaway 2018-07-03 12:06:47 -07:00
parent 136ff6735a
commit 998651102d
No known key found for this signature in database
GPG key ID: 10B62F8A7CAD7A41
2 changed files with 86 additions and 33 deletions

View file

@ -1690,45 +1690,45 @@ def installed(
# checks reinstall targets works.
pkg_ret = {}
if 'pkg.hold' in __salt__:
if 'hold' in kwargs:
try:
if kwargs['hold']:
hold_ret = __salt__['pkg.hold'](
name=name, pkgs=pkgs, sources=sources
)
else:
hold_ret = __salt__['pkg.unhold'](
name=name, pkgs=pkgs, sources=sources
)
except (CommandExecutionError, SaltInvocationError) as exc:
comment.append(str(exc))
if 'pkg.hold' in __salt__:
if 'hold' in kwargs:
try:
if kwargs['hold']:
hold_ret = __salt__['pkg.hold'](
name=name, pkgs=desired, sources=sources
)
else:
hold_ret = __salt__['pkg.unhold'](
name=name, pkgs=desired, sources=sources
)
except (CommandExecutionError, SaltInvocationError) as exc:
comment.append(str(exc))
ret = {'name': name,
'changes': changes,
'result': False,
'comment': '\n'.join(comment)}
if warnings:
ret.setdefault('warnings', []).extend(warnings)
return ret
else:
if 'result' in hold_ret and not hold_ret['result']:
ret = {'name': name,
'changes': changes,
'changes': {},
'result': False,
'comment': '\n'.join(comment)}
'comment': 'An error was encountered while '
'holding/unholding package(s): {0}'
.format(hold_ret['comment'])}
if warnings:
ret.setdefault('warnings', []).extend(warnings)
return ret
else:
if 'result' in hold_ret and not hold_ret['result']:
ret = {'name': name,
'changes': {},
'result': False,
'comment': 'An error was encountered while '
'holding/unholding package(s): {0}'
.format(hold_ret['comment'])}
if warnings:
ret.setdefault('warnings', []).extend(warnings)
return ret
else:
modified_hold = [hold_ret[x] for x in hold_ret
if hold_ret[x]['changes']]
not_modified_hold = [hold_ret[x] for x in hold_ret
if not hold_ret[x]['changes']
and hold_ret[x]['result']]
failed_hold = [hold_ret[x] for x in hold_ret
if not hold_ret[x]['result']]
modified_hold = [hold_ret[x] for x in hold_ret
if hold_ret[x]['changes']]
not_modified_hold = [hold_ret[x] for x in hold_ret
if not hold_ret[x]['changes']
and hold_ret[x]['result']]
failed_hold = [hold_ret[x] for x in hold_ret
if not hold_ret[x]['result']]
if to_unpurge:
changes['purge_desired'] = __salt__['lowpkg.unpurge'](*to_unpurge)
@ -1805,6 +1805,10 @@ def installed(
if len(changes[change_name]['old']) > 0:
changes[change_name]['old'] += '\n'
changes[change_name]['old'] += '{0}'.format(i['changes']['old'])
else:
comment.append(i['comment'])
changes[change_name] = {}
changes[change_name]['new'] = '{0}'.format(i['changes']['new'])
# Any requested packages that were not targeted for install or reinstall
if not_modified:

View file

@ -736,3 +736,52 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
self.assertEqual(ret_comment, 'An error was encountered while installing/updating group '
'\'handle_missing_pkg_group\': Group \'handle_missing_pkg_group\' '
'not found.')
@requires_system_grains
def test_pkg_015_installed_held(self, grains=None): # pylint: disable=unused-argument
'''
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' and os_family.lower() != 'debian':
self.skipTest('Test only runs on RedHat or Debian 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]
# 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,
)
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], {'new': 'hold', 'old': 'install'})
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)