Merge pull request #48932 from twangboy/fix_win_repo

Fix pkg.install when pkg already installed
This commit is contained in:
Nicole Thomas 2018-08-09 13:45:50 -04:00 committed by GitHub
commit 9b6a9ff4f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 169 additions and 29 deletions

View File

@ -1092,7 +1092,8 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
.. versionadded:: 2016.11.0
Returns:
dict: Return a dict containing the new package names and versions
dict: Return a dict containing the new package names and versions. If
the package is already installed, an empty dict is returned.
If the package is installed by ``pkg.install``:
@ -1101,12 +1102,6 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
{'<package>': {'old': '<old-version>',
'new': '<new-version>'}}
If the package is already installed:
.. code-block:: cfg
{'<package>': {'current': '<current-version>'}}
The following example will refresh the winrepo and install a single
package, 7zip.
@ -1200,7 +1195,6 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
# Loop through each package
changed = []
latest = []
for pkg_name, options in six.iteritems(pkg_params):
# Load package information for the package
@ -1212,28 +1206,33 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
ret[pkg_name] = 'Unable to locate package {0}'.format(pkg_name)
continue
version_num = options.get('version', '')
version_num = options.get('version')
# Using the salt cmdline with version=5.3 might be interpreted
# as a float it must be converted to a string in order for
# string matching to work.
if not isinstance(version_num, six.string_types) and version_num is not None:
version_num = six.text_type(version_num)
# If the version was not passed, version_num will be None
if not version_num:
if pkg_name in old:
log.debug('A version (%s) already installed for package '
'%s', version_num, pkg_name)
log.debug('pkg.install: \'%s\' version \'%s\' is already installed',
pkg_name, old[pkg_name][0])
continue
# following can be version number or latest or Not Found
# Get the most recent version number available from winrepo.p
# May also return `latest` or an empty string
version_num = _get_latest_pkg_version(pkginfo)
if version_num == 'latest' and 'latest' not in pkginfo:
# Get the most recent version number available from winrepo.p
# May also return `latest` or an empty string
version_num = _get_latest_pkg_version(pkginfo)
# Check if the version is already installed
if version_num in old.get(pkg_name, []):
# Desired version number already installed
ret[pkg_name] = {'current': version_num}
log.debug('pkg.install: \'%s\' version \'%s\' is already installed',
pkg_name, version_num)
continue
# If version number not installed, is the version available?
elif version_num != 'latest' and version_num not in pkginfo:
@ -1242,9 +1241,6 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
ret[pkg_name] = {'not found': version_num}
continue
if 'latest' in pkginfo:
latest.append(pkg_name)
# Get the installer settings from winrepo.p
installer = pkginfo[version_num].get('installer', '')
cache_dir = pkginfo[version_num].get('cache_dir', False)
@ -1329,18 +1325,18 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
# Fix non-windows slashes
cached_pkg = cached_pkg.replace('/', '\\')
cache_path, _ = os.path.split(cached_pkg)
cache_path = os.path.dirname(cached_pkg)
# Compare the hash sums
source_hash = pkginfo[version_num].get('source_hash', False)
if source_hash:
source_sum = _get_source_sum(source_hash, cached_pkg, saltenv)
log.debug('Source %s hash: %s',
log.debug('pkg.install: Source %s hash: %s',
source_sum['hash_type'], source_sum['hsum'])
cached_pkg_sum = salt.utils.hashutils.get_hash(cached_pkg,
source_sum['hash_type'])
log.debug('Package %s hash: %s',
log.debug('pkg.install: Package %s hash: %s',
source_sum['hash_type'], cached_pkg_sum)
if source_sum['hsum'] != cached_pkg_sum:
@ -1348,7 +1344,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
("Source hash '{0}' does not match package hash"
" '{1}'").format(source_sum['hsum'], cached_pkg_sum)
)
log.debug('Source hash matches package hash.')
log.debug('pkg.install: Source hash matches package hash.')
# Get install flags
@ -1459,15 +1455,6 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
# preparation for the comparison below.
__salt__['pkg_resource.stringify'](old)
# For installers that have no specific version (ie: chrome)
# The software definition file will have a version of 'latest'
# In that case there's no way to know which version has been installed
# Just return the current installed version
if latest:
for pkg_name in latest:
if old.get(pkg_name, 'old') == new.get(pkg_name, 'new'):
ret[pkg_name] = {'current': new[pkg_name]}
# Check for changes in the registry
difference = salt.utils.data.compare_dicts(old, new)

View File

@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
'''
Tests for the win_pkg module
'''
# Import Python Libs
from __future__ import absolute_import, unicode_literals, print_function
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, patch
from tests.support.unit import TestCase
# Import Salt Libs
import salt.modules.pkg_resource as pkg_resource
import salt.modules.win_pkg as win_pkg
class WinPkgInstallTestCase(TestCase, LoaderModuleMockMixin):
'''
Test cases for salt.modules.win_pkg
'''
def setup_loader_modules(self):
pkg_info = {
'3.03': {
'full_name': 'Nullsoft Install System',
'installer': 'http://download.sourceforge.net/project/nsis/NSIS%203/3.03/nsis-3.03-setup.exe',
'install_flags': '/S',
'uninstaller': '%PROGRAMFILES(x86)%\\NSIS\\uninst-nsis.exe',
'uninstall_flags': '/S',
'msiexec': False,
'reboot': False
},
'3.02': {
'full_name': 'Nullsoft Install System',
'installer': 'http://download.sourceforge.net/project/nsis/NSIS%203/3.02/nsis-3.02-setup.exe',
'install_flags': '/S',
'uninstaller': '%PROGRAMFILES(x86)%\\NSIS\\uninst-nsis.exe',
'uninstall_flags': '/S',
'msiexec': False,
'reboot': False
}
}
return{
win_pkg: {
'_get_latest_package_version': MagicMock(return_value='3.03'),
'_get_package_info': MagicMock(return_value=pkg_info),
'__salt__': {
'pkg_resource.add_pkg': pkg_resource.add_pkg,
'pkg_resource.parse_targets': pkg_resource.parse_targets,
'pkg_resource.sort_pkglist': pkg_resource.sort_pkglist,
'pkg_resource.stringify': pkg_resource.stringify,
},
},
pkg_resource: {
'__grains__': {
'os': 'Windows'
}
},
}
def test_pkg_install_not_found(self):
'''
Test pkg.install when the Version is NOT FOUND in the Software
Definition
'''
ret_reg = {'Nullsoft Install System': '3.03'}
# The 2nd time it's run with stringify
se_list_pkgs = {'nsis': ['3.03']}
with patch.object(win_pkg, 'list_pkgs', return_value=se_list_pkgs), \
patch.object(win_pkg, '_get_reg_software', return_value=ret_reg):
expected = {'nsis': {'not found': '3.01'}}
result = win_pkg.install(name='nsis', version='3.01')
self.assertDictEqual(expected, result)
def test_pkg_install_rollback(self):
'''
test pkg.install rolling back to a previous version
'''
ret_reg = {'Nullsoft Install System': '3.03'}
# The 2nd time it's run, pkg.list_pkgs uses with stringify
se_list_pkgs = [{'nsis': ['3.03']},
{'nsis': '3.02'}]
with patch.object(win_pkg, 'list_pkgs', side_effect=se_list_pkgs), \
patch.object(
win_pkg, '_get_reg_software', return_value=ret_reg), \
patch.dict(
win_pkg.__salt__,
{'cp.is_cached': MagicMock(return_value=False)}), \
patch.dict(
win_pkg.__salt__,
{'cp.cache_file':
MagicMock(return_value='C:\\fake\\path.exe')}), \
patch.dict(
win_pkg.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
expected = {'nsis': {'new': '3.02', 'old': '3.03'}}
result = win_pkg.install(name='nsis', version='3.02')
self.assertDictEqual(expected, result)
def test_pkg_install_existing(self):
'''
test pkg.install when the package is already installed
no version passed
'''
ret_reg = {'Nullsoft Install System': '3.03'}
# The 2nd time it's run, pkg.list_pkgs uses with stringify
se_list_pkgs = {'nsis': ['3.03']}
with patch.object(win_pkg, 'list_pkgs', return_value=se_list_pkgs), \
patch.object(
win_pkg, '_get_reg_software', return_value=ret_reg), \
patch.dict(
win_pkg.__salt__,
{'cp.is_cached': MagicMock(return_value=False)}), \
patch.dict(
win_pkg.__salt__,
{'cp.cache_file':
MagicMock(return_value='C:\\fake\\path.exe')}), \
patch.dict(
win_pkg.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
expected = {}
result = win_pkg.install(name='nsis')
self.assertDictEqual(expected, result)
def test_pkg_install_existing_with_version(self):
'''
test pkg.install when the package is already installed
A version is passed
'''
ret_reg = {'Nullsoft Install System': '3.03'}
# The 2nd time it's run, pkg.list_pkgs uses with stringify
se_list_pkgs = {'nsis': ['3.03']}
with patch.object(win_pkg, 'list_pkgs', return_value=se_list_pkgs), \
patch.object(
win_pkg, '_get_reg_software', return_value=ret_reg), \
patch.dict(
win_pkg.__salt__,
{'cp.is_cached': MagicMock(return_value=False)}), \
patch.dict(
win_pkg.__salt__,
{'cp.cache_file':
MagicMock(return_value='C:\\fake\\path.exe')}), \
patch.dict(
win_pkg.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
expected = {}
result = win_pkg.install(name='nsis', version='3.03')
self.assertDictEqual(expected, result)