mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #45483 from rallytime/merge-2017.7
[2017.7] Merge forward from 2016.11 to 2017.7
This commit is contained in:
commit
b3dc758ab0
6 changed files with 209 additions and 103 deletions
|
@ -9,10 +9,14 @@ Windows
|
|||
=======
|
||||
Execution module pkg
|
||||
--------------------
|
||||
Significate changes (PR #43708, damon-atkins) have been made to the pkg execution module. Users should test this release against their existing package sls definition files.
|
||||
Significate changes (PR #43708 & #45390, damon-atkins) have been made to the pkg execution module. Users should test this release against their existing package sls definition files.
|
||||
|
||||
- ``pkg.list_available`` no longer defaults to refreshing the winrepo meta database.
|
||||
- ``pkg.install`` without a ``version`` parameter no longer upgrades software if the software is already installed. Use ``pkg.install version=latest`` or in a state use ``pkg.latest`` to get the old behavior.
|
||||
- ``pkg.list_pkgs`` now returns multiple versions if software installed more than once.
|
||||
- ``pkg.list_pkgs`` now returns 'Not Found' when the version is not found instead of '(value not set)' which matches the contents of the sls definitions.
|
||||
- ``pkg.remove()`` will wait upto 3 seconds (normally about a second) to detect changes in the registry after removing software, improving reporting of version changes.
|
||||
- ``pkg.remove()`` can remove ``latest`` software, if ``latest`` is defined in sls definition.
|
||||
- Documentation was update for the execution module to match the style in new versions, some corrections as well.
|
||||
- All install/remove commands are prefix with cmd.exe shell and cmdmod is called with a command line string instead of a list. Some sls files in saltstack/salt-winrepo-ng expected the commands to be prefixed with cmd.exe (i.e. the use of ``&``).
|
||||
- Some execution module functions results, now behavour more like their Unix/Linux versions.
|
||||
|
|
|
@ -61,7 +61,7 @@ def run_command(jboss_config, command, fail_on_error=True):
|
|||
command
|
||||
Command to execute against jboss instance
|
||||
fail_on_error (default=True)
|
||||
Is true, raise CommandExecutionException exception if execution fails.
|
||||
Is true, raise CommandExecutionError exception if execution fails.
|
||||
If false, 'success' property of the returned dictionary is set to False
|
||||
|
||||
CLI Example:
|
||||
|
@ -93,7 +93,7 @@ def run_operation(jboss_config, operation, fail_on_error=True, retries=1):
|
|||
An operation to execute against jboss instance
|
||||
|
||||
fail_on_error (default=True)
|
||||
Is true, raise CommandExecutionException exception if execution fails.
|
||||
Is true, raise CommandExecutionError exception if execution fails.
|
||||
If false, 'success' property of the returned dictionary is set to False
|
||||
retries:
|
||||
Number of retries in case of "JBAS012144: Could not connect to remote" error.
|
||||
|
|
|
@ -382,10 +382,18 @@ def read_value(hive, key, vname=None, use_32bit_registry=False):
|
|||
except WindowsError: # pylint: disable=E0602
|
||||
ret['vdata'] = ('(value not set)')
|
||||
ret['vtype'] = 'REG_SZ'
|
||||
except pywintypes.error as exc: # pylint: disable=E0602
|
||||
msg = 'Cannot find {0} in {1}\\{2}' \
|
||||
''.format(local_vname, local_hive, local_key)
|
||||
log.trace(exc)
|
||||
log.trace(msg)
|
||||
ret['comment'] = msg
|
||||
ret['success'] = False
|
||||
except pywintypes.error as exc: # pylint: disable=E0602
|
||||
log.debug(exc)
|
||||
log.debug('Cannot find key: {0}\\{1}'.format(local_hive, local_key))
|
||||
ret['comment'] = 'Cannot find key: {0}\\{1}'.format(local_hive, local_key)
|
||||
msg = 'Cannot find key: {0}\\{1}'.format(local_hive, local_key)
|
||||
log.trace(exc)
|
||||
log.trace(msg)
|
||||
ret['comment'] = msg
|
||||
ret['success'] = False
|
||||
return ret
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ As the creation of this metadata can take some time, the
|
|||
:conf_minion:`winrepo_cache_expire_min` minion config option can be used to
|
||||
suppress refreshes when the metadata is less than a given number of seconds
|
||||
old.
|
||||
|
||||
.. note::
|
||||
Version numbers can be `version number string`, `latest` and `Not Found`.
|
||||
Where `Not Found` means this module was not able to determine the version of
|
||||
the software installed, it can also be used as the version number in sls
|
||||
definitions file in these cases. Versions numbers are sorted in order of
|
||||
0,`Not Found`,`order version numbers`,...,`latest`.
|
||||
|
||||
'''
|
||||
|
||||
# Import python future libs
|
||||
|
@ -61,7 +69,6 @@ import salt.syspaths
|
|||
import salt.payload
|
||||
from salt.exceptions import MinionError
|
||||
from salt.utils.versions import LooseVersion
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Define the module's virtual name
|
||||
|
@ -386,20 +393,23 @@ def list_pkgs(versions_as_list=False, **kwargs):
|
|||
|
||||
ret = {}
|
||||
name_map = _get_name_map(saltenv)
|
||||
for pkg_name, val in six.iteritems(_get_reg_software()):
|
||||
for pkg_name, val_list in six.iteritems(_get_reg_software()):
|
||||
if pkg_name in name_map:
|
||||
key = name_map[pkg_name]
|
||||
if val in ['(value not set)', 'Not Found', None, False]:
|
||||
# Look up version from winrepo
|
||||
pkg_info = _get_package_info(key, saltenv=saltenv)
|
||||
if not pkg_info:
|
||||
continue
|
||||
for pkg_ver in pkg_info:
|
||||
if pkg_info[pkg_ver]['full_name'] == pkg_name:
|
||||
val = pkg_ver
|
||||
for val in val_list:
|
||||
if val == 'Not Found':
|
||||
# Look up version from winrepo
|
||||
pkg_info = _get_package_info(key, saltenv=saltenv)
|
||||
if not pkg_info:
|
||||
continue
|
||||
for pkg_ver in pkg_info.keys():
|
||||
if pkg_info[pkg_ver]['full_name'] == pkg_name:
|
||||
val = pkg_ver
|
||||
__salt__['pkg_resource.add_pkg'](ret, key, val)
|
||||
else:
|
||||
key = pkg_name
|
||||
__salt__['pkg_resource.add_pkg'](ret, key, val)
|
||||
for val in val_list:
|
||||
__salt__['pkg_resource.add_pkg'](ret, key, val)
|
||||
|
||||
__salt__['pkg_resource.sort_pkglist'](ret)
|
||||
if not versions_as_list:
|
||||
|
@ -407,21 +417,6 @@ def list_pkgs(versions_as_list=False, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def _search_software(target):
|
||||
'''
|
||||
This searches the msi product databases for name matches of the list of
|
||||
target products, it will return a dict with values added to the list passed
|
||||
in
|
||||
'''
|
||||
search_results = {}
|
||||
software = dict(_get_reg_software().items())
|
||||
for key, value in six.iteritems(software):
|
||||
if key is not None:
|
||||
if target.lower() in key.lower():
|
||||
search_results[key] = value
|
||||
return search_results
|
||||
|
||||
|
||||
def _get_reg_software():
|
||||
'''
|
||||
This searches the uninstall keys in the registry to find a match in the sub
|
||||
|
@ -445,29 +440,62 @@ def _get_reg_software():
|
|||
None]
|
||||
|
||||
reg_software = {}
|
||||
|
||||
hive = 'HKLM'
|
||||
key = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
|
||||
|
||||
def update(hive, key, reg_key, use_32bit):
|
||||
|
||||
# 2018 this code has been update to reflect some of utils/pkg/win.py logic
|
||||
# i.e. check_reg, and checking of DisplayName and DisplayVersion.
|
||||
d_name = ''
|
||||
d_vers = ''
|
||||
|
||||
d_name = __salt__['reg.read_value'](hive,
|
||||
'{0}\\{1}'.format(key, reg_key),
|
||||
'DisplayName',
|
||||
use_32bit)['vdata']
|
||||
d_name_regdata = __salt__['reg.read_value'](hive,
|
||||
'{0}\\{1}'.format(key, reg_key),
|
||||
'DisplayName',
|
||||
use_32bit)
|
||||
if (not d_name_regdata['success'] or
|
||||
d_name_regdata['vtype'] not in ['REG_SZ', 'REG_EXPAND_SZ'] or
|
||||
d_name_regdata['vdata'] in ['(value not set)', None, False]):
|
||||
return
|
||||
d_name = d_name_regdata['vdata']
|
||||
|
||||
d_vers = __salt__['reg.read_value'](hive,
|
||||
'{0}\\{1}'.format(key, reg_key),
|
||||
'DisplayVersion',
|
||||
use_32bit)['vdata']
|
||||
d_vers_regdata = __salt__['reg.read_value'](hive,
|
||||
'{0}\\{1}'.format(key, reg_key),
|
||||
'DisplayVersion',
|
||||
use_32bit)
|
||||
if (not d_vers_regdata['success'] or
|
||||
d_vers_regdata['vtype'] not in ['REG_SZ', 'REG_EXPAND_SZ', 'REG_DWORD'] or
|
||||
d_vers_regdata['vdata'] in [None, False]):
|
||||
return
|
||||
|
||||
if isinstance(d_vers_regdata['vdata'], int):
|
||||
d_vers = six.text_type(d_vers_regdata['vdata'])
|
||||
else:
|
||||
d_vers = d_vers_regdata['vdata']
|
||||
|
||||
if not d_vers or d_vers == '(value not set)':
|
||||
d_vers = 'Not Found'
|
||||
|
||||
check_ok = False
|
||||
for check_reg in ['UninstallString', 'QuietUninstallString', 'ModifyPath']:
|
||||
check_regdata = __salt__['reg.read_value'](hive,
|
||||
'{0}\\{1}'.format(key, reg_key),
|
||||
check_reg,
|
||||
use_32bit)
|
||||
if (not check_regdata['success'] or
|
||||
check_regdata['vtype'] not in ['REG_SZ', 'REG_EXPAND_SZ'] or
|
||||
check_regdata['vdata'] in ['(value not set)', None, False]):
|
||||
continue
|
||||
else:
|
||||
check_ok = True
|
||||
|
||||
if not check_ok:
|
||||
return
|
||||
|
||||
if d_name not in ignore_list:
|
||||
# some MS Office updates don't register a product name which means
|
||||
# their information is useless
|
||||
reg_software.update({d_name: six.text_type(d_vers)})
|
||||
reg_software.setdefault(d_name, []).append(d_vers)
|
||||
|
||||
for reg_key in __salt__['reg.list_keys'](hive, key):
|
||||
update(hive, key, reg_key, False)
|
||||
|
@ -823,7 +851,7 @@ def _repo_process_pkg_sls(filename, short_path_name, ret, successful_verbose):
|
|||
if config:
|
||||
revmap = {}
|
||||
errors = []
|
||||
for pkgname, versions in six.iteritems(config):
|
||||
for pkgname, version_list in six.iteritems(config):
|
||||
if pkgname in ret['repo']:
|
||||
log.error(
|
||||
'package \'%s\' within \'%s\' already defined, skipping',
|
||||
|
@ -831,7 +859,7 @@ def _repo_process_pkg_sls(filename, short_path_name, ret, successful_verbose):
|
|||
)
|
||||
errors.append('package \'{0}\' already defined'.format(pkgname))
|
||||
break
|
||||
for version_str, repodata in six.iteritems(versions):
|
||||
for version_str, repodata in six.iteritems(version_list):
|
||||
# Ensure version is a string/unicode
|
||||
if not isinstance(version_str, six.string_types):
|
||||
msg = (
|
||||
|
@ -1104,7 +1132,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
}
|
||||
|
||||
# Get a list of currently installed software for comparison at the end
|
||||
old = list_pkgs(saltenv=saltenv, refresh=refresh)
|
||||
old = list_pkgs(saltenv=saltenv, refresh=refresh, versions_as_list=True)
|
||||
|
||||
# Loop through each package
|
||||
changed = []
|
||||
|
@ -1121,16 +1149,20 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
continue
|
||||
|
||||
# Get the version number passed or the latest available (must be a string)
|
||||
version_num = ''
|
||||
version_num = None
|
||||
if options:
|
||||
version_num = options.get('version', '')
|
||||
version_num = options.get('version', None)
|
||||
# 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:
|
||||
if not isinstance(version_num, six.text_type) and version_num is not None:
|
||||
version_num = six.text_type(version_num)
|
||||
|
||||
if not version_num:
|
||||
if pkg_name in old:
|
||||
log.debug('A version ({0}) already installed for package '
|
||||
'{1}'.format(version_num, pkg_name))
|
||||
continue
|
||||
# following can be version number or latest or Not Found
|
||||
version_num = _get_latest_pkg_version(pkginfo)
|
||||
|
||||
|
@ -1138,8 +1170,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
version_num = _get_latest_pkg_version(pkginfo)
|
||||
|
||||
# Check if the version is already installed
|
||||
if version_num in old.get(pkg_name, '').split(',') \
|
||||
or (old.get(pkg_name, '') == 'Not Found'):
|
||||
if version_num in old.get(pkg_name, []):
|
||||
# Desired version number already installed
|
||||
ret[pkg_name] = {'current': version_num}
|
||||
continue
|
||||
|
@ -1311,9 +1342,9 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
else:
|
||||
|
||||
# Make sure the task is running, try for 5 secs
|
||||
from time import time
|
||||
t_end = time() + 5
|
||||
while time() < t_end:
|
||||
t_end = time.time() + 5
|
||||
while time.time() < t_end:
|
||||
time.sleep(0.25)
|
||||
task_running = __salt__['task.status'](
|
||||
'update-salt-software') == 'Running'
|
||||
if task_running:
|
||||
|
@ -1360,7 +1391,11 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
ret[pkg_name] = {'install status': 'failed'}
|
||||
|
||||
# Get a new list of installed software
|
||||
new = list_pkgs(saltenv=saltenv)
|
||||
new = list_pkgs(saltenv=saltenv, refresh=False)
|
||||
|
||||
# Take the "old" package list and convert the values to strings in
|
||||
# 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'
|
||||
|
@ -1401,9 +1436,9 @@ def upgrade(**kwargs):
|
|||
|
||||
salt '*' pkg.upgrade
|
||||
'''
|
||||
log.warning('pkg.upgrade not implemented on Windows yet')
|
||||
refresh = salt.utils.is_true(kwargs.get('refresh', True))
|
||||
saltenv = kwargs.get('saltenv', 'base')
|
||||
log.warning('pkg.upgrade not implemented on Windows yet refresh:%s saltenv:%s', refresh, saltenv)
|
||||
# Uncomment the below once pkg.upgrade has been implemented
|
||||
|
||||
# if salt.utils.is_true(refresh):
|
||||
|
@ -1411,7 +1446,7 @@ def upgrade(**kwargs):
|
|||
return {}
|
||||
|
||||
|
||||
def remove(name=None, pkgs=None, version=None, **kwargs):
|
||||
def remove(name=None, pkgs=None, **kwargs):
|
||||
'''
|
||||
Remove the passed package(s) from the system using winrepo
|
||||
|
||||
|
@ -1422,6 +1457,12 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
The name(s) of the package(s) to be uninstalled. Can be a
|
||||
single package or a comma delimited list of packages, no spaces.
|
||||
|
||||
pkgs (list):
|
||||
A list of packages to delete. Must be passed as a python list. The
|
||||
``name`` parameter will be ignored if this option is passed.
|
||||
|
||||
Kwargs:
|
||||
|
||||
version (str):
|
||||
The version of the package to be uninstalled. If this option is
|
||||
used to to uninstall multiple packages, then this version will be
|
||||
|
@ -1429,11 +1470,6 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
uninstalling a single package. If this parameter is omitted, the
|
||||
latest version will be uninstalled.
|
||||
|
||||
pkgs (list):
|
||||
A list of packages to delete. Must be passed as a python list. The
|
||||
``name`` parameter will be ignored if this option is passed.
|
||||
|
||||
Kwargs:
|
||||
saltenv (str): Salt environment. Default ``base``
|
||||
refresh (bool): Refresh package metadata. Default ``False``
|
||||
|
||||
|
@ -1473,7 +1509,7 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
old = list_pkgs(saltenv=saltenv, refresh=refresh, versions_as_list=True)
|
||||
|
||||
# Loop through each package
|
||||
changed = []
|
||||
changed = [] # list of changed package names
|
||||
for pkgname, version_num in six.iteritems(pkg_params):
|
||||
|
||||
# Load package information for the package
|
||||
|
@ -1486,44 +1522,57 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
ret[pkgname] = msg
|
||||
continue
|
||||
|
||||
# Check to see if package is installed on the system
|
||||
if pkgname not in old:
|
||||
log.debug('%s %s not installed', pkgname, version_num if version_num else '')
|
||||
ret[pkgname] = {'current': 'not installed'}
|
||||
continue
|
||||
|
||||
removal_targets = []
|
||||
# Only support a single version number
|
||||
if version_num is not None:
|
||||
# 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 version_num not in pkginfo and 'latest' in pkginfo:
|
||||
version_num = 'latest'
|
||||
elif 'latest' in pkginfo:
|
||||
version_num = 'latest'
|
||||
version_num = six.text_type(version_num)
|
||||
|
||||
# Check to see if package is installed on the system
|
||||
removal_targets = []
|
||||
if pkgname not in old:
|
||||
log.error('%s %s not installed', pkgname, version)
|
||||
ret[pkgname] = {'current': 'not installed'}
|
||||
continue
|
||||
# At least one version of the software is installed.
|
||||
if version_num is None:
|
||||
for ver_install in old[pkgname]:
|
||||
if ver_install not in pkginfo and 'latest' in pkginfo:
|
||||
log.debug('%s %s using package latest entry to to remove', pkgname, version_num)
|
||||
removal_targets.append('latest')
|
||||
else:
|
||||
removal_targets.append(ver_install)
|
||||
else:
|
||||
if version_num is None:
|
||||
removal_targets.extend(old[pkgname])
|
||||
elif version_num not in old[pkgname] \
|
||||
and 'Not Found' not in old[pkgname] \
|
||||
and version_num != 'latest':
|
||||
log.error('%s %s not installed', pkgname, version)
|
||||
ret[pkgname] = {
|
||||
'current': '{0} not installed'.format(version_num)
|
||||
if version_num in pkginfo:
|
||||
# we known how to remove this version
|
||||
if version_num in old[pkgname]:
|
||||
removal_targets.append(version_num)
|
||||
else:
|
||||
log.debug('%s %s not installed', pkgname, version_num)
|
||||
ret[pkgname] = {'current': '{0} not installed'.format(version_num)}
|
||||
continue
|
||||
elif 'latest' in pkginfo:
|
||||
# we do not have version entry, assume software can self upgrade and use latest
|
||||
log.debug('%s %s using package latest entry to to remove', pkgname, version_num)
|
||||
removal_targets.append('latest')
|
||||
|
||||
if not removal_targets:
|
||||
log.error('%s %s no definition to remove this version', pkgname, version_num)
|
||||
ret[pkgname] = {
|
||||
'current': '{0} no definition, cannot removed'.format(version_num)
|
||||
}
|
||||
continue
|
||||
else:
|
||||
removal_targets.append(version_num)
|
||||
continue
|
||||
|
||||
for target in removal_targets:
|
||||
# Get the uninstaller
|
||||
uninstaller = pkginfo[target].get('uninstaller', '')
|
||||
cache_dir = pkginfo[target].get('cache_dir', False)
|
||||
uninstall_flags = pkginfo[target].get('uninstall_flags', '')
|
||||
|
||||
# If no uninstaller found, use the installer
|
||||
if not uninstaller:
|
||||
# If no uninstaller found, use the installer with uninstall flags
|
||||
if not uninstaller and uninstall_flags:
|
||||
uninstaller = pkginfo[target].get('installer', '')
|
||||
|
||||
# If still no uninstaller found, fail
|
||||
|
@ -1532,7 +1581,7 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
'No installer or uninstaller configured for package %s',
|
||||
pkgname,
|
||||
)
|
||||
ret[pkgname] = {'no uninstaller': target}
|
||||
ret[pkgname] = {'no uninstaller defined': target}
|
||||
continue
|
||||
|
||||
# Where is the uninstaller
|
||||
|
@ -1591,9 +1640,6 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
|
||||
# os.path.expandvars is not required as we run everything through cmd.exe /s /c
|
||||
|
||||
# Get uninstall flags
|
||||
uninstall_flags = pkginfo[target].get('uninstall_flags', '')
|
||||
|
||||
if kwargs.get('extra_uninstall_flags'):
|
||||
uninstall_flags = '{0} {1}'.format(
|
||||
uninstall_flags, kwargs.get('extra_uninstall_flags', ''))
|
||||
|
@ -1615,6 +1661,7 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
arguments = '{0} {1}'.format(arguments, uninstall_flags)
|
||||
|
||||
# Uninstall the software
|
||||
changed.append(pkgname)
|
||||
# Check Use Scheduler Option
|
||||
if pkginfo[target].get('use_scheduler', False):
|
||||
# Create Scheduled Task
|
||||
|
@ -1664,29 +1711,32 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
|||
ret[pkgname] = {'uninstall status': 'failed'}
|
||||
|
||||
# Get a new list of installed software
|
||||
new = list_pkgs(saltenv=saltenv)
|
||||
new = list_pkgs(saltenv=saltenv, refresh=False)
|
||||
|
||||
# Take the "old" package list and convert the values to strings in
|
||||
# preparation for the comparison below.
|
||||
__salt__['pkg_resource.stringify'](old)
|
||||
|
||||
# Check for changes in the registry
|
||||
difference = salt.utils.compare_dicts(old, new)
|
||||
tries = 0
|
||||
while not all(name in difference for name in changed) and tries <= 1000:
|
||||
new = list_pkgs(saltenv=saltenv)
|
||||
found_chgs = all(name in difference for name in changed)
|
||||
end_t = time.time() + 3 # give it 3 seconds to catch up.
|
||||
while not found_chgs and time.time() < end_t:
|
||||
time.sleep(0.5)
|
||||
new = list_pkgs(saltenv=saltenv, refresh=False)
|
||||
difference = salt.utils.compare_dicts(old, new)
|
||||
tries += 1
|
||||
if tries == 1000:
|
||||
ret['_comment'] = 'Registry not updated.'
|
||||
found_chgs = all(name in difference for name in changed)
|
||||
|
||||
if not found_chgs:
|
||||
log.warning('Expected changes for package removal may not have occured')
|
||||
|
||||
# Compare the software list before and after
|
||||
# Add the difference to ret
|
||||
ret.update(difference)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def purge(name=None, pkgs=None, version=None, **kwargs):
|
||||
def purge(name=None, pkgs=None, **kwargs):
|
||||
'''
|
||||
Package purges are not supported, this function is identical to
|
||||
``remove()``.
|
||||
|
@ -1724,7 +1774,6 @@ def purge(name=None, pkgs=None, version=None, **kwargs):
|
|||
'''
|
||||
return remove(name=name,
|
||||
pkgs=pkgs,
|
||||
version=version,
|
||||
**kwargs)
|
||||
|
||||
|
||||
|
@ -1808,6 +1857,11 @@ def _reverse_cmp_pkg_versions(pkg1, pkg2):
|
|||
|
||||
|
||||
def _get_latest_pkg_version(pkginfo):
|
||||
'''
|
||||
Returns the latest version of the package.
|
||||
Will return 'latest' or version number string, and
|
||||
'Not Found' if 'Not Found' is the only entry.
|
||||
'''
|
||||
if len(pkginfo) == 1:
|
||||
return next(six.iterkeys(pkginfo))
|
||||
try:
|
||||
|
|
|
@ -786,6 +786,13 @@ def latest(name,
|
|||
)
|
||||
remote_loc = None
|
||||
|
||||
if depth is not None and remote_rev_type != 'branch':
|
||||
return _fail(
|
||||
ret,
|
||||
'When \'depth\' is used, \'rev\' must be set to the name of a '
|
||||
'branch on the remote repository'
|
||||
)
|
||||
|
||||
if remote_rev is None and not bare:
|
||||
if rev != 'HEAD':
|
||||
# A specific rev is desired, but that rev doesn't exist on the
|
||||
|
@ -1663,7 +1670,7 @@ def latest(name,
|
|||
if remote != 'origin':
|
||||
clone_opts.extend(['--origin', remote])
|
||||
if depth is not None:
|
||||
clone_opts.extend(['--depth', str(depth)])
|
||||
clone_opts.extend(['--depth', str(depth), '--branch', rev])
|
||||
|
||||
# We're cloning a fresh repo, there is no local branch or revision
|
||||
local_branch = local_rev = None
|
||||
|
|
|
@ -446,6 +446,39 @@ class GitTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
if exc.errno != errno.ENOENT:
|
||||
raise exc
|
||||
|
||||
def test_latest_depth(self):
|
||||
'''
|
||||
Test running git.latest state using the "depth" argument to limit the
|
||||
history. See #45394.
|
||||
'''
|
||||
name = os.path.join(TMP, 'salt_repo')
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'git.latest',
|
||||
name='https://{0}/saltstack/salt-test-repo.git'.format(self.__domain),
|
||||
rev='HEAD',
|
||||
target=name,
|
||||
depth=1
|
||||
)
|
||||
# HEAD is not a branch, this should fail
|
||||
self.assertSaltFalseReturn(ret)
|
||||
self.assertIn(
|
||||
'must be set to the name of a branch',
|
||||
ret[next(iter(ret))]['comment']
|
||||
)
|
||||
|
||||
ret = self.run_state(
|
||||
'git.latest',
|
||||
name='https://{0}/saltstack/salt-test-repo.git'.format(self.__domain),
|
||||
rev='non-default-branch',
|
||||
target=name,
|
||||
depth=1
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
self.assertTrue(os.path.isdir(os.path.join(name, '.git')))
|
||||
finally:
|
||||
shutil.rmtree(name, ignore_errors=True)
|
||||
|
||||
def test_present(self):
|
||||
'''
|
||||
git.present
|
||||
|
|
Loading…
Add table
Reference in a new issue