From 5bab2422bad1def24b69c77e11f7fe1011f871792487e360847e3b363af302f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Fri, 26 Apr 2019 13:19:34 +0000 Subject: [PATCH] Remove unused patch OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=135 --- zypper-add-root-configuration-parameter.patch | 2147 ----------------- 1 file changed, 2147 deletions(-) delete mode 100644 zypper-add-root-configuration-parameter.patch diff --git a/zypper-add-root-configuration-parameter.patch b/zypper-add-root-configuration-parameter.patch deleted file mode 100644 index 69e513d..0000000 --- a/zypper-add-root-configuration-parameter.patch +++ /dev/null @@ -1,2147 +0,0 @@ -From e20116f09c1f68238008c13a0517a8d36a7be56a Mon Sep 17 00:00:00 2001 -From: Alberto Planas -Date: Wed, 17 Oct 2018 11:58:04 +0200 -Subject: [PATCH] zypper: add root configuration parameter - -Fix typo in comment - -lowpkg: add parameter to change root directory - -The CLI rpm command allows the --root parameter to change the -expected location where the rpm database can be found. - -This patch add a new optional parameter in the public interface -to allow the set of the new root location. - -Update the tests to use the extra parameter. - -Add root parameter into the zypper module - -The zypper CLI provides a way to change the path where zypper expect -to find the required configuration files and repositories. - -This feature is useful to bootstrap chroot environments, inspect -repositories and packages from locally mounted devices, or help -during the installation of a new OS from the SUSE family. - -This patch add the root optional parameter for each command in the -public interface, and fix the tests. - -pkg: Transfer optional parameters to lower levels. - -pkgrepo: Transfer optional parameters to lower levels. - -zypper: fix the reset after the call - -_Zypper class take note when a .call() is done, to clean up the data -when we access to some attribute. - -This produces a bug when two calls are one after another an we set -some attributes via the __call__ method, as whatever is set will be -cleared after the first attribute is accessed. - -For example: - -zypper.attrib.call(..) -zypper(root=root).otherattrib.call(..) - -The first call will set __called as True, and the reset of the inner -state of zypper will be cleared when otherattrib is accessed, -cleanning the status for __root. - -This patch makes sure to clean the status also during the __call__ -method, avoiding the cleanning when the attribute is accessed. - -zypper: add no_recommends parameter - -Add no_recommends parameter to install and upgrade actions. ---- - salt/modules/rpm_lowpkg.py | 101 +++++-- - salt/modules/zypperpkg.py | 390 ++++++++++++++++++-------- - salt/states/pkg.py | 28 +- - salt/states/pkgrepo.py | 14 +- - tests/unit/modules/test_rpm_lowpkg.py | 92 +++++- - tests/unit/modules/test_zypperpkg.py | 45 +-- - tests/unit/states/test_pkg.py | 7 +- - 7 files changed, 488 insertions(+), 189 deletions(-) - -diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py -index 893ae4f817..e577c4391a 100644 ---- a/salt/modules/rpm_lowpkg.py -+++ b/salt/modules/rpm_lowpkg.py -@@ -76,7 +76,7 @@ def bin_pkg_info(path, saltenv='base'): - minion so that it can be examined. - - saltenv : base -- Salt fileserver envrionment from which to retrieve the package. Ignored -+ Salt fileserver environment from which to retrieve the package. Ignored - if ``path`` is a local file path on the minion. - - CLI Example: -@@ -128,12 +128,15 @@ def bin_pkg_info(path, saltenv='base'): - return ret - - --def list_pkgs(*packages): -+def list_pkgs(*packages, **kwargs): - ''' - List the packages currently installed in a dict:: - - {'': ''} - -+ root -+ use root as top level directory (default: "/") -+ - CLI Example: - - .. code-block:: bash -@@ -141,8 +144,11 @@ def list_pkgs(*packages): - salt '*' lowpkg.list_pkgs - ''' - pkgs = {} -- cmd = ['rpm', '-q' if packages else '-qa', -- '--queryformat', r'%{NAME} %{VERSION}\n'] -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ cmd.extend(['-q' if packages else '-qa', -+ '--queryformat', r'%{NAME} %{VERSION}\n']) - if packages: - cmd.extend(packages) - out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False) -@@ -158,6 +164,9 @@ def verify(*packages, **kwargs): - ''' - Runs an rpm -Va on a system, and returns the results in a dict - -+ root -+ use root as top level directory (default: "/") -+ - Files with an attribute of config, doc, ghost, license or readme in the - package header can be ignored using the ``ignore_types`` keyword argument - -@@ -199,6 +208,8 @@ def verify(*packages, **kwargs): - verify_options = [x.strip() for x in six.text_type(verify_options).split(',')] - - cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) - cmd.extend(['--' + x for x in verify_options]) - if packages: - cmd.append('-V') -@@ -258,6 +269,9 @@ def modified(*packages, **flags): - - .. versionadded:: 2015.5.0 - -+ root -+ use root as top level directory (default: "/") -+ - CLI examples: - - .. code-block:: bash -@@ -266,10 +280,12 @@ def modified(*packages, **flags): - salt '*' lowpkg.modified httpd postfix - salt '*' lowpkg.modified - ''' -- ret = __salt__['cmd.run_all']( -- ['rpm', '-Va'] + list(packages), -- output_loglevel='trace', -- python_shell=False) -+ cmd = ['rpm'] -+ if flags.get('root'): -+ cmd.extend(['--root', flags.pop('root')]) -+ cmd.append('-Va') -+ cmd.extend(packages) -+ ret = __salt__['cmd.run_all'](cmd, output_loglevel='trace', python_shell=False) - - data = {} - -@@ -324,12 +340,15 @@ def modified(*packages, **flags): - return filtered_data - - --def file_list(*packages): -+def file_list(*packages, **kwargs): - ''' - List the files that belong to a package. Not specifying any packages will - return a list of _every_ file on the system's rpm database (not generally - recommended). - -+ root -+ use root as top level directory (default: "/") -+ - CLI Examples: - - .. code-block:: bash -@@ -338,12 +357,15 @@ def file_list(*packages): - salt '*' lowpkg.file_list httpd postfix - salt '*' lowpkg.file_list - ''' -- if not packages: -- cmd = ['rpm', '-qla'] -- else: -- cmd = ['rpm', '-ql'] -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ -+ cmd.append('-ql' if packages else '-qla') -+ if packages: - # Can't concatenate a tuple, must do a list.extend() - cmd.extend(packages) -+ - ret = __salt__['cmd.run']( - cmd, - output_loglevel='trace', -@@ -351,12 +373,15 @@ def file_list(*packages): - return {'errors': [], 'files': ret} - - --def file_dict(*packages): -+def file_dict(*packages, **kwargs): - ''' - List the files that belong to a package, sorted by group. Not specifying - any packages will return a list of _every_ file on the system's rpm - database (not generally recommended). - -+ root -+ use root as top level directory (default: "/") -+ - CLI Examples: - - .. code-block:: bash -@@ -368,8 +393,11 @@ def file_dict(*packages): - errors = [] - ret = {} - pkgs = {} -- cmd = ['rpm', '-q' if packages else '-qa', -- '--queryformat', r'%{NAME} %{VERSION}\n'] -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ cmd.extend(['-q' if packages else '-qa', -+ '--queryformat', r'%{NAME} %{VERSION}\n']) - if packages: - cmd.extend(packages) - out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False) -@@ -380,8 +408,10 @@ def file_dict(*packages): - comps = line.split() - pkgs[comps[0]] = {'version': comps[1]} - for pkg in pkgs: -- files = [] -- cmd = ['rpm', '-ql', pkg] -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ cmd.extend(['-ql', pkg]) - out = __salt__['cmd.run']( - ['rpm', '-ql', pkg], - output_loglevel='trace', -@@ -390,7 +420,7 @@ def file_dict(*packages): - return {'errors': errors, 'packages': ret} - - --def owner(*paths): -+def owner(*paths, **kwargs): - ''' - Return the name of the package that owns the file. Multiple file paths can - be passed. If a single path is passed, a string will be returned, -@@ -400,6 +430,9 @@ def owner(*paths): - If the file is not owned by a package, or is not present on the minion, - then an empty string will be returned for that path. - -+ root -+ use root as top level directory (default: "/") -+ - CLI Examples: - - .. code-block:: bash -@@ -411,7 +444,10 @@ def owner(*paths): - return '' - ret = {} - for path in paths: -- cmd = ['rpm', '-qf', '--queryformat', '%{name}', path] -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ cmd.extend(['-qf', '--queryformat', '%{name}', path]) - ret[path] = __salt__['cmd.run_stdout'](cmd, - output_loglevel='trace', - python_shell=False) -@@ -471,6 +507,9 @@ def info(*packages, **kwargs): - :param all_versions: - Return information for all installed versions of the packages - -+ :param root: -+ use root as top level directory (default: "/") -+ - :return: - - CLI example: -@@ -493,7 +532,14 @@ def info(*packages, **kwargs): - else: - size_tag = '%{SIZE}' - -- cmd = packages and "rpm -q {0}".format(' '.join(packages)) or "rpm -qa" -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ if packages: -+ cmd.append('-q') -+ cmd.extend(packages) -+ else: -+ cmd.append('-qa') - - # Construct query format - attr_map = { -@@ -544,6 +590,7 @@ def info(*packages, **kwargs): - query.append(attr_map['description']) - query.append("-----\\n") - -+ cmd = ' '.join(cmd) - call = __salt__['cmd.run_all'](cmd + (" --queryformat '{0}'".format(''.join(query))), - output_loglevel='trace', env={'TZ': 'UTC'}, clean_env=True) - if call['retcode'] != 0: -@@ -744,10 +791,13 @@ def version_cmp(ver1, ver2, ignore_epoch=False): - return salt.utils.versions.version_cmp(ver1, ver2, ignore_epoch=False) - - --def checksum(*paths): -+def checksum(*paths, **kwargs): - ''' - Return if the signature of a RPM file is valid. - -+ root -+ use root as top level directory (default: "/") -+ - CLI Example: - - .. code-block:: bash -@@ -760,9 +810,14 @@ def checksum(*paths): - if not paths: - raise CommandExecutionError("No package files has been specified.") - -+ cmd = ['rpm'] -+ if kwargs.get('root'): -+ cmd.extend(['--root', kwargs['root']]) -+ cmd.extend(['-K', '--quiet']) - for package_file in paths: -+ cmd_ = cmd + [package_file] - ret[package_file] = (bool(__salt__['file.file_exists'](package_file)) and -- not __salt__['cmd.retcode'](["rpm", "-K", "--quiet", package_file], -+ not __salt__['cmd.retcode'](cmd_, - ignore_retcode=True, - output_loglevel='trace', - python_shell=False)) -diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index 92e7052020..c442337c58 100644 ---- a/salt/modules/zypperpkg.py -+++ b/salt/modules/zypperpkg.py -@@ -99,6 +99,7 @@ class _Zypper(object): - - LOCK_EXIT_CODE = 7 - XML_DIRECTIVES = ['-x', '--xmlout'] -+ # ZYPPER_LOCK is not affected by --root - ZYPPER_LOCK = '/var/run/zypp.pid' - TAG_RELEASED = 'zypper/released' - TAG_BLOCKED = 'zypper/blocked' -@@ -107,7 +108,6 @@ class _Zypper(object): - ''' - Constructor - ''' -- self.__called = False - self._reset() - - def _reset(self): -@@ -129,6 +129,10 @@ class _Zypper(object): - self.__refresh = False - self.__ignore_repo_failure = False - self.__systemd_scope = False -+ self.__root = None -+ -+ # Call status -+ self.__called = False - - def __call__(self, *args, **kwargs): - ''' -@@ -136,11 +140,17 @@ class _Zypper(object): - :param kwargs: - :return: - ''' -+ # Reset after the call -+ if self.__called: -+ self._reset() -+ - # Ignore exit code for 106 (repo is not available) - if 'no_repo_failure' in kwargs: - self.__ignore_repo_failure = kwargs['no_repo_failure'] - if 'systemd_scope' in kwargs: - self.__systemd_scope = kwargs['systemd_scope'] -+ if 'root' in kwargs: -+ self.__root = kwargs['root'] - return self - - def __getattr__(self, item): -@@ -153,7 +163,6 @@ class _Zypper(object): - # Reset after the call - if self.__called: - self._reset() -- self.__called = False - - if item == 'xml': - self.__xml = True -@@ -284,6 +293,8 @@ class _Zypper(object): - self.__cmd.append('--xmlout') - if not self.__refresh: - self.__cmd.append('--no-refresh') -+ if self.__root: -+ self.__cmd.extend(['--root', self.__root]) - - self.__cmd.extend(args) - kwargs['output_loglevel'] = 'trace' -@@ -442,7 +453,7 @@ def _clean_cache(): - __context__.pop(cache_name, None) - - --def list_upgrades(refresh=True, **kwargs): -+def list_upgrades(refresh=True, root=None, **kwargs): - ''' - List all available package upgrades on this system - -@@ -451,6 +462,9 @@ def list_upgrades(refresh=True, **kwargs): - If set to False it depends on zypper if a refresh is - executed. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -458,7 +472,7 @@ def list_upgrades(refresh=True, **kwargs): - salt '*' pkg.list_upgrades - ''' - if refresh: -- refresh_db() -+ refresh_db(root) - - ret = dict() - cmd = ['list-updates'] -@@ -467,7 +481,7 @@ def list_upgrades(refresh=True, **kwargs): - if not isinstance(repo_name, six.string_types): - repo_name = six.text_type(repo_name) - cmd.extend(['--repo', repo_name]) -- for update_node in __zypper__.nolock.xml.call(*cmd).getElementsByTagName('update'): -+ for update_node in __zypper__(root=root).nolock.xml.call(*cmd).getElementsByTagName('update'): - if update_node.getAttribute('kind') == 'package': - ret[update_node.getAttribute('name')] = update_node.getAttribute('edition') - -@@ -504,6 +518,9 @@ def info_installed(*names, **kwargs): - :param all_versions: - Include information for all versions of the packages installed on the minion. - -+ :param root: -+ Operate on a different root directory. -+ - CLI example: - - .. code-block:: bash -@@ -544,6 +561,9 @@ def info_available(*names, **kwargs): - If set to False it depends on zypper if a refresh is - executed or not. - -+ root -+ operate on a different root directory. -+ - CLI example: - - .. code-block:: bash -@@ -558,9 +578,11 @@ def info_available(*names, **kwargs): - else: - names = sorted(list(set(names))) - -+ root = kwargs.get('root', None) -+ - # Refresh db before extracting the latest package - if kwargs.get('refresh', True): -- refresh_db() -+ refresh_db(root) - - pkg_info = [] - batch = names[:] -@@ -569,7 +591,8 @@ def info_available(*names, **kwargs): - # Run in batches - while batch: - pkg_info.extend(re.split(r"Information for package*", -- __zypper__.nolock.call('info', '-t', 'package', *batch[:batch_size]))) -+ __zypper__(root=root).nolock.call('info', '-t', 'package', -+ *batch[:batch_size]))) - batch = batch[batch_size:] - - for pkg_data in pkg_info: -@@ -629,6 +652,9 @@ def latest_version(*names, **kwargs): - If set to False it depends on zypper if a refresh is - executed or not. - -+ root -+ operate on a different root directory. -+ - CLI example: - - .. code-block:: bash -@@ -671,6 +697,9 @@ def upgrade_available(name, **kwargs): - If set to False it depends on zypper if a refresh is - executed or not. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -687,6 +716,9 @@ def version(*names, **kwargs): - installed. If more than one package name is specified, a dict of - name/version pairs is returned. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -719,7 +751,7 @@ def version_cmp(ver1, ver2, ignore_epoch=False): - return __salt__['lowpkg.version_cmp'](ver1, ver2, ignore_epoch=ignore_epoch) - - --def list_pkgs(versions_as_list=False, **kwargs): -+def list_pkgs(versions_as_list=False, root=None, **kwargs): - ''' - List the packages currently installed as a dict. By default, the dict - contains versions as a comma separated string:: -@@ -731,6 +763,9 @@ def list_pkgs(versions_as_list=False, **kwargs): - - {'': ['', '']} - -+ root: -+ operate on a different root directory. -+ - attr: - If a list of package attributes is specified, returned value will - contain them in addition to version, eg.:: -@@ -770,10 +805,14 @@ def list_pkgs(versions_as_list=False, **kwargs): - - contextkey = 'pkg.list_pkgs' - -+ # TODO(aplanas): this cached value depends on the parameters - if contextkey not in __context__: - ret = {} -- cmd = ['rpm', '-qa', '--queryformat', -- salt.utils.pkg.rpm.QUERYFORMAT.replace('%{REPOID}', '(none)') + '\n'] -+ cmd = ['rpm'] -+ if root: -+ cmd.extend(['--root', root]) -+ cmd.extend(['-qa', '--queryformat', -+ salt.utils.pkg.rpm.QUERYFORMAT.replace('%{REPOID}', '(none)') + '\n']) - output = __salt__['cmd.run'](cmd, - python_shell=False, - output_loglevel='trace') -@@ -859,6 +898,9 @@ def list_repo_pkgs(*args, **kwargs): - When ``True``, the return data for each package will be organized by - repository. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash -@@ -891,7 +933,8 @@ def list_repo_pkgs(*args, **kwargs): - return True - return False - -- for node in __zypper__.xml.call('se', '-s', *targets).getElementsByTagName('solvable'): -+ root = kwargs.get('root') or None -+ for node in __zypper__(root=root).xml.call('se', '-s', *targets).getElementsByTagName('solvable'): - pkginfo = dict(node.attributes.items()) - try: - if pkginfo['kind'] != 'package': -@@ -933,23 +976,27 @@ def list_repo_pkgs(*args, **kwargs): - return byrepo_ret - - --def _get_configured_repos(): -+def _get_configured_repos(root=None): - ''' - Get all the info about repositories from the configurations. - ''' - -+ repos = os.path.join(root, os.path.relpath(REPOS, os.path.sep)) if root else REPOS - repos_cfg = configparser.ConfigParser() -- repos_cfg.read([REPOS + '/' + fname for fname in os.listdir(REPOS) if fname.endswith(".repo")]) -+ if os.path.exists(repos): -+ repos_cfg.read([repos + '/' + fname for fname in os.listdir(repos) if fname.endswith(".repo")]) -+ else: -+ log.error('Repositories not found in {}'.format(repos)) - - return repos_cfg - - --def _get_repo_info(alias, repos_cfg=None): -+def _get_repo_info(alias, repos_cfg=None, root=None): - ''' - Get one repo meta-data. - ''' - try: -- meta = dict((repos_cfg or _get_configured_repos()).items(alias)) -+ meta = dict((repos_cfg or _get_configured_repos(root=root)).items(alias)) - meta['alias'] = alias - for key, val in six.iteritems(meta): - if val in ['0', '1']: -@@ -961,51 +1008,60 @@ def _get_repo_info(alias, repos_cfg=None): - return {} - - --def get_repo(repo, **kwargs): # pylint: disable=unused-argument -+def get_repo(repo, root=None, **kwargs): # pylint: disable=unused-argument - ''' - Display a repo. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash - - salt '*' pkg.get_repo alias - ''' -- return _get_repo_info(repo) -+ return _get_repo_info(repo, root=root) - - --def list_repos(): -+def list_repos(root=None): - ''' - Lists all repos. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash - - salt '*' pkg.list_repos - ''' -- repos_cfg = _get_configured_repos() -+ repos_cfg = _get_configured_repos(root=root) - all_repos = {} - for alias in repos_cfg.sections(): -- all_repos[alias] = _get_repo_info(alias, repos_cfg=repos_cfg) -+ all_repos[alias] = _get_repo_info(alias, repos_cfg=repos_cfg, root=root) - - return all_repos - - --def del_repo(repo): -+def del_repo(repo, root=None): - ''' - Delete a repo. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash - - salt '*' pkg.del_repo alias - ''' -- repos_cfg = _get_configured_repos() -+ repos_cfg = _get_configured_repos(root=root) - for alias in repos_cfg.sections(): - if alias == repo: -- doc = __zypper__.xml.call('rr', '--loose-auth', '--loose-query', alias) -+ doc = __zypper__(root=root).xml.call('rr', '--loose-auth', '--loose-query', alias) - msg = doc.getElementsByTagName('message') - if doc.getElementsByTagName('progress') and msg: - return { -@@ -1044,6 +1100,9 @@ def mod_repo(repo, **kwargs): - If set to True, automatically trust and import public GPG key for - the repository. - -+ root -+ operate on a different root directory. -+ - Key/Value pairs may also be removed from a repo's configuration by setting - a key to a blank value. Bear in mind that a name cannot be deleted, and a - URL can only be deleted if a ``mirrorlist`` is specified (or vice versa). -@@ -1056,7 +1115,8 @@ def mod_repo(repo, **kwargs): - salt '*' pkg.mod_repo alias url= mirrorlist=http://host.com/ - ''' - -- repos_cfg = _get_configured_repos() -+ root = kwargs.get('root') or None -+ repos_cfg = _get_configured_repos(root=root) - added = False - - # An attempt to add new one? -@@ -1076,7 +1136,7 @@ def mod_repo(repo, **kwargs): - - # Is there already such repo under different alias? - for alias in repos_cfg.sections(): -- repo_meta = _get_repo_info(alias, repos_cfg=repos_cfg) -+ repo_meta = _get_repo_info(alias, repos_cfg=repos_cfg, root=root) - - # Complete user URL, in case it is not - new_url = _urlparse(url) -@@ -1098,17 +1158,17 @@ def mod_repo(repo, **kwargs): - ) - - # Add new repo -- __zypper__.xml.call('ar', url, repo) -+ __zypper__(root=root).xml.call('ar', url, repo) - - # Verify the repository has been added -- repos_cfg = _get_configured_repos() -+ repos_cfg = _get_configured_repos(root=root) - if repo not in repos_cfg.sections(): - raise CommandExecutionError( - 'Failed add new repository \'{0}\' for unspecified reason. ' - 'Please check zypper logs.'.format(repo)) - added = True - -- repo_info = _get_repo_info(repo) -+ repo_info = _get_repo_info(repo, root=root) - if ( - not added and 'baseurl' in kwargs and - not (kwargs['baseurl'] == repo_info['baseurl']) -@@ -1117,8 +1177,8 @@ def mod_repo(repo, **kwargs): - # we need to remove the repository and add it again with the new baseurl - repo_info.update(kwargs) - repo_info.setdefault('cache', False) -- del_repo(repo) -- return mod_repo(repo, **repo_info) -+ del_repo(repo, root=root) -+ return mod_repo(repo, root=root, **repo_info) - - # Modify added or existing repo according to the options - cmd_opt = [] -@@ -1151,7 +1211,7 @@ def mod_repo(repo, **kwargs): - - if cmd_opt: - cmd_opt = global_cmd_opt + ['mr'] + cmd_opt + [repo] -- __zypper__.refreshable.xml.call(*cmd_opt) -+ __zypper__(root=root).refreshable.xml.call(*cmd_opt) - - comment = None - if call_refresh: -@@ -1159,23 +1219,26 @@ def mod_repo(repo, **kwargs): - # --gpg-auto-import-keys is not doing anything - # so we need to specifically refresh here with --gpg-auto-import-keys - refresh_opts = global_cmd_opt + ['refresh'] + [repo] -- __zypper__.xml.call(*refresh_opts) -+ __zypper__(root=root).xml.call(*refresh_opts) - elif not added and not cmd_opt: - comment = 'Specified arguments did not result in modification of repo' - -- repo = get_repo(repo) -+ repo = get_repo(repo, root=root) - if comment: - repo['comment'] = comment - - return repo - - --def refresh_db(): -+def refresh_db(root=None): - ''' - Force a repository refresh by calling ``zypper refresh --force``, return a dict:: - - {'': Bool} - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -1185,7 +1248,7 @@ def refresh_db(): - # Remove rtag file to keep multiple refreshes from happening in pkg states - salt.utils.pkg.clear_rtag(__opts__) - ret = {} -- out = __zypper__.refreshable.call('refresh', '--force') -+ out = __zypper__(root=root).refreshable.call('refresh', '--force') - - for line in out.splitlines(): - if not line: -@@ -1213,6 +1276,8 @@ def install(name=None, - skip_verify=False, - version=None, - ignore_repo_failure=False, -+ no_recommends=False, -+ root=None, - **kwargs): - ''' - .. versionchanged:: 2015.8.12,2016.3.3,2016.11.0 -@@ -1301,6 +1366,12 @@ def install(name=None, - Zypper returns error code 106 if one of the repositories are not available for various reasons. - In case to set strict check, this parameter needs to be set to True. Default: False. - -+ no_recommends -+ Do not install recommended packages, only required ones. -+ -+ root -+ operate on a different root directory. -+ - diff_attr: - If a list of package attributes is specified, returned value will - contain them, eg.:: -@@ -1340,7 +1411,7 @@ def install(name=None, - 'arch': ''}}} - ''' - if refresh: -- refresh_db() -+ refresh_db(root) - - try: - pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](name, pkgs, sources, **kwargs) -@@ -1350,7 +1421,7 @@ def install(name=None, - if pkg_params is None or len(pkg_params) == 0: - return {} - -- version_num = Wildcard(__zypper__)(name, version) -+ version_num = Wildcard(__zypper__(root=root))(name, version) - - if version_num: - if pkgs is None and sources is None: -@@ -1375,7 +1446,7 @@ def install(name=None, - targets.append(target) - elif pkg_type == 'advisory': - targets = [] -- cur_patches = list_patches() -+ cur_patches = list_patches(root=root) - for advisory_id in pkg_params: - if advisory_id not in cur_patches: - raise CommandExecutionError('Advisory id "{0}" not found'.format(advisory_id)) -@@ -1385,7 +1456,7 @@ def install(name=None, - targets = pkg_params - - diff_attr = kwargs.get("diff_attr") -- old = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded() -+ old = list_pkgs(attr=diff_attr, root=root) if not downloadonly else list_downloaded(root) - downgrades = [] - if fromrepo: - fromrepoopt = ['--force', '--force-resolution', '--from', fromrepo] -@@ -1404,6 +1475,8 @@ def install(name=None, - cmd_install.append('--download-only') - if fromrepo: - cmd_install.extend(fromrepoopt) -+ if no_recommends: -+ cmd_install.append('--no-recommends') - - errors = [] - if pkg_type == 'advisory': -@@ -1415,7 +1488,7 @@ def install(name=None, - while targets: - cmd = cmd_install + targets[:500] - targets = targets[500:] -- for line in __zypper__(no_repo_failure=ignore_repo_failure, systemd_scope=systemd_scope).call(*cmd).splitlines(): -+ for line in __zypper__(no_repo_failure=ignore_repo_failure, systemd_scope=systemd_scope, root=root).call(*cmd).splitlines(): - match = re.match(r"^The selected package '([^']+)'.+has lower version", line) - if match: - downgrades.append(match.group(1)) -@@ -1423,10 +1496,10 @@ def install(name=None, - while downgrades: - cmd = cmd_install + ['--force'] + downgrades[:500] - downgrades = downgrades[500:] -- __zypper__(no_repo_failure=ignore_repo_failure).call(*cmd) -+ __zypper__(no_repo_failure=ignore_repo_failure, root=root).call(*cmd) - - _clean_cache() -- new = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded() -+ new = list_pkgs(attr=diff_attr, root=root) if not downloadonly else list_downloaded(root) - ret = salt.utils.data.compare_dicts(old, new) - - if errors: -@@ -1446,6 +1519,8 @@ def upgrade(refresh=True, - fromrepo=None, - novendorchange=False, - skip_verify=False, -+ no_recommends=False, -+ root=None, - **kwargs): # pylint: disable=unused-argument - ''' - .. versionchanged:: 2015.8.12,2016.3.3,2016.11.0 -@@ -1485,6 +1560,12 @@ def upgrade(refresh=True, - skip_verify - Skip the GPG verification check (e.g., ``--no-gpg-checks``) - -+ no_recommends -+ Do not install recommended packages, only required ones. -+ -+ root -+ Operate on a different root directory. -+ - Returns a dictionary containing the changes: - - .. code-block:: python -@@ -1507,7 +1588,7 @@ def upgrade(refresh=True, - cmd_update.insert(0, '--no-gpg-checks') - - if refresh: -- refresh_db() -+ refresh_db(root) - - if dryrun: - cmd_update.append('--dry-run') -@@ -1526,16 +1607,20 @@ def upgrade(refresh=True, - else: - log.warning('Disabling vendor changes is not supported on this Zypper version') - -+ if no_recommends: -+ cmd_update.append('--no-recommends') -+ log.info('Disabling recommendations') -+ - if dryrun: - # Creates a solver test case for debugging. - log.info('Executing debugsolver and performing a dry-run dist-upgrade') -- __zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update + ['--debug-solver']) -+ __zypper__(systemd_scope=_systemd_scope(), root=root).noraise.call(*cmd_update + ['--debug-solver']) - -- old = list_pkgs() -+ old = list_pkgs(root=root) - -- __zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update) -+ __zypper__(systemd_scope=_systemd_scope(), root=root).noraise.call(*cmd_update) - _clean_cache() -- new = list_pkgs() -+ new = list_pkgs(root=root) - ret = salt.utils.data.compare_dicts(old, new) - - if __zypper__.exit_code not in __zypper__.SUCCESS_EXIT_CODES: -@@ -1556,7 +1641,7 @@ def upgrade(refresh=True, - return ret - - --def _uninstall(name=None, pkgs=None): -+def _uninstall(name=None, pkgs=None, root=None): - ''' - Remove and purge do identical things but with different Zypper commands, - this function performs the common logic. -@@ -1566,7 +1651,7 @@ def _uninstall(name=None, pkgs=None): - except MinionError as exc: - raise CommandExecutionError(exc) - -- old = list_pkgs() -+ old = list_pkgs(root=root) - targets = [] - for target in pkg_params: - # Check if package version set to be removed is actually installed: -@@ -1582,11 +1667,11 @@ def _uninstall(name=None, pkgs=None): - - errors = [] - while targets: -- __zypper__(systemd_scope=systemd_scope).call('remove', *targets[:500]) -+ __zypper__(systemd_scope=systemd_scope, root=root).call('remove', *targets[:500]) - targets = targets[500:] - - _clean_cache() -- ret = salt.utils.data.compare_dicts(old, list_pkgs()) -+ ret = salt.utils.data.compare_dicts(old, list_pkgs(root=root)) - - if errors: - raise CommandExecutionError( -@@ -1623,7 +1708,7 @@ def normalize_name(name): - return name - - --def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument -+def remove(name=None, pkgs=None, root=None, **kwargs): # pylint: disable=unused-argument - ''' - .. versionchanged:: 2015.8.12,2016.3.3,2016.11.0 - On minions running systemd>=205, `systemd-run(1)`_ is now used to -@@ -1651,6 +1736,9 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument - A list of packages to delete. Must be passed as a python list. The - ``name`` parameter will be ignored if this option is passed. - -+ root -+ Operate on a different root directory. -+ - .. versionadded:: 0.16.0 - - -@@ -1664,10 +1752,10 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument - salt '*' pkg.remove ,, - salt '*' pkg.remove pkgs='["foo", "bar"]' - ''' -- return _uninstall(name=name, pkgs=pkgs) -+ return _uninstall(name=name, pkgs=pkgs, root=root) - - --def purge(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument -+def purge(name=None, pkgs=None, root=None, **kwargs): # pylint: disable=unused-argument - ''' - .. versionchanged:: 2015.8.12,2016.3.3,2016.11.0 - On minions running systemd>=205, `systemd-run(1)`_ is now used to -@@ -1696,6 +1784,9 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument - A list of packages to delete. Must be passed as a python list. The - ``name`` parameter will be ignored if this option is passed. - -+ root -+ Operate on a different root directory. -+ - .. versionadded:: 0.16.0 - - -@@ -1709,13 +1800,16 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument - salt '*' pkg.purge ,, - salt '*' pkg.purge pkgs='["foo", "bar"]' - ''' -- return _uninstall(name=name, pkgs=pkgs) -+ return _uninstall(name=name, pkgs=pkgs, root=root) - - --def list_locks(): -+def list_locks(root=None): - ''' - List current package locks. - -+ root -+ operate on a different root directory. -+ - Return a dict containing the locked package with attributes:: - - {'': {'case_sensitive': '', -@@ -1729,8 +1823,9 @@ def list_locks(): - salt '*' pkg.list_locks - ''' - locks = {} -- if os.path.exists(LOCKS): -- with salt.utils.files.fopen(LOCKS) as fhr: -+ _locks = os.path.join(root, os.path.relpath(LOCKS, os.path.sep)) if root else LOCKS -+ try: -+ with salt.utils.files.fopen(_locks) as fhr: - items = salt.utils.stringutils.to_unicode(fhr.read()).split('\n\n') - for meta in [item.split('\n') for item in items]: - lock = {} -@@ -1739,15 +1834,22 @@ def list_locks(): - lock.update(dict([tuple([i.strip() for i in element.split(':', 1)]), ])) - if lock.get('solvable_name'): - locks[lock.pop('solvable_name')] = lock -+ except IOError: -+ pass -+ except Exception: -+ log.warning('Detected a problem when accessing {}'.format(_locks)) - - return locks - - --def clean_locks(): -+def clean_locks(root=None): - ''' - Remove unused locks that do not currently (with regard to repositories - used) lock any package. - -+ root -+ Operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -1756,10 +1858,11 @@ def clean_locks(): - ''' - LCK = "removed" - out = {LCK: 0} -- if not os.path.exists("/etc/zypp/locks"): -+ locks = os.path.join(root, os.path.relpath(LOCKS, os.path.sep)) if root else LOCKS -+ if not os.path.exists(locks): - return out - -- for node in __zypper__.xml.call('cl').getElementsByTagName("message"): -+ for node in __zypper__(root=root).xml.call('cl').getElementsByTagName("message"): - text = node.childNodes[0].nodeValue.lower() - if text.startswith(LCK): - out[LCK] = text.split(" ")[1] -@@ -1772,6 +1875,9 @@ def unhold(name=None, pkgs=None, **kwargs): - ''' - Remove specified package lock. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -1781,12 +1887,13 @@ def unhold(name=None, pkgs=None, **kwargs): - salt '*' pkg.remove_lock pkgs='["foo", "bar"]' - ''' - ret = {} -+ root = kwargs.get('root') - if (not name and not pkgs) or (name and pkgs): - raise CommandExecutionError('Name or packages must be specified.') - elif name: - pkgs = [name] - -- locks = list_locks() -+ locks = list_locks(root) - try: - pkgs = list(__salt__['pkg_resource.parse_targets'](pkgs)[0].keys()) - except MinionError as exc: -@@ -1803,12 +1910,12 @@ def unhold(name=None, pkgs=None, **kwargs): - ret[pkg]['comment'] = 'Package {0} unable to be unheld.'.format(pkg) - - if removed: -- __zypper__.call('rl', *removed) -+ __zypper__(root=root).call('rl', *removed) - - return ret - - --def remove_lock(packages, **kwargs): # pylint: disable=unused-argument -+def remove_lock(packages, root=None, **kwargs): # pylint: disable=unused-argument - ''' - Remove specified package lock. - -@@ -1821,7 +1928,7 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument - salt '*' pkg.remove_lock pkgs='["foo", "bar"]' - ''' - salt.utils.versions.warn_until('Sodium', 'This function is deprecated. Please use unhold() instead.') -- locks = list_locks() -+ locks = list_locks(root) - try: - packages = list(__salt__['pkg_resource.parse_targets'](packages)[0].keys()) - except MinionError as exc: -@@ -1836,7 +1943,7 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument - missing.append(pkg) - - if removed: -- __zypper__.call('rl', *removed) -+ __zypper__(root=root).call('rl', *removed) - - return {'removed': len(removed), 'not_found': missing} - -@@ -1859,12 +1966,13 @@ def hold(name=None, pkgs=None, **kwargs): - :return: - ''' - ret = {} -+ root = kwargs.get('root') - if (not name and not pkgs) or (name and pkgs): - raise CommandExecutionError('Name or packages must be specified.') - elif name: - pkgs = [name] - -- locks = list_locks() -+ locks = list_locks(root=root) - added = [] - try: - pkgs = list(__salt__['pkg_resource.parse_targets'](pkgs)[0].keys()) -@@ -1880,15 +1988,18 @@ def hold(name=None, pkgs=None, **kwargs): - ret[pkg]['comment'] = 'Package {0} is already set to be held.'.format(pkg) - - if added: -- __zypper__.call('al', *added) -+ __zypper__(root=root).call('al', *added) - - return ret - - --def add_lock(packages, **kwargs): # pylint: disable=unused-argument -+def add_lock(packages, root=None, **kwargs): # pylint: disable=unused-argument - ''' - Add a package lock. Specify packages to lock by exact name. - -+ root -+ operate on a different root directory. -+ - CLI Example: - - .. code-block:: bash -@@ -1898,7 +2009,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument - salt '*' pkg.add_lock pkgs='["foo", "bar"]' - ''' - salt.utils.versions.warn_until('Sodium', 'This function is deprecated. Please use hold() instead.') -- locks = list_locks() -+ locks = list_locks(root) - added = [] - try: - packages = list(__salt__['pkg_resource.parse_targets'](packages)[0].keys()) -@@ -1910,7 +2021,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument - added.append(pkg) - - if added: -- __zypper__.call('al', *added) -+ __zypper__(root=root).call('al', *added) - - return {'added': len(added), 'packages': added} - -@@ -1920,7 +2031,9 @@ def verify(*names, **kwargs): - Runs an rpm -Va on a system, and returns the results in a dict - - Files with an attribute of config, doc, ghost, license or readme in the -- package header can be ignored using the ``ignore_types`` keyword argument -+ package header can be ignored using the ``ignore_types`` keyword argument. -+ -+ The root parameter can also be passed via the keyword argument. - - CLI Example: - -@@ -1934,12 +2047,14 @@ def verify(*names, **kwargs): - return __salt__['lowpkg.verify'](*names, **kwargs) - - --def file_list(*packages): -+def file_list(*packages, **kwargs): - ''' - List the files that belong to a package. Not specifying any packages will - return a list of *every* file on the system's rpm database (not generally - recommended). - -+ The root parameter can also be passed via the keyword argument. -+ - CLI Examples: - - .. code-block:: bash -@@ -1948,15 +2063,17 @@ def file_list(*packages): - salt '*' pkg.file_list httpd postfix - salt '*' pkg.file_list - ''' -- return __salt__['lowpkg.file_list'](*packages) -+ return __salt__['lowpkg.file_list'](*packages, **kwargs) - - --def file_dict(*packages): -+def file_dict(*packages, **kwargs): - ''' - List the files that belong to a package, grouped by package. Not - specifying any packages will return a list of *every* file on the system's - rpm database (not generally recommended). - -+ The root parameter can also be passed via the keyword argument. -+ - CLI Examples: - - .. code-block:: bash -@@ -1965,7 +2082,7 @@ def file_dict(*packages): - salt '*' pkg.file_list httpd postfix - salt '*' pkg.file_list - ''' -- return __salt__['lowpkg.file_dict'](*packages) -+ return __salt__['lowpkg.file_dict'](*packages, **kwargs) - - - def modified(*packages, **flags): -@@ -2004,6 +2121,9 @@ def modified(*packages, **flags): - capabilities - Include only files where capabilities differ or not. Note: supported only on newer RPM versions. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash -@@ -2017,7 +2137,7 @@ def modified(*packages, **flags): - return __salt__['lowpkg.modified'](*packages, **flags) - - --def owner(*paths): -+def owner(*paths, **kwargs): - ''' - Return the name of the package that owns the file. Multiple file paths can - be passed. If a single path is passed, a string will be returned, -@@ -2027,6 +2147,8 @@ def owner(*paths): - If the file is not owned by a package, or is not present on the minion, - then an empty string will be returned for that path. - -+ The root parameter can also be passed via the keyword argument. -+ - CLI Examples: - - .. code-block:: bash -@@ -2034,15 +2156,15 @@ def owner(*paths): - salt '*' pkg.owner /usr/bin/apachectl - salt '*' pkg.owner /usr/bin/apachectl /etc/httpd/conf/httpd.conf - ''' -- return __salt__['lowpkg.owner'](*paths) -+ return __salt__['lowpkg.owner'](*paths, **kwargs) - - --def _get_patterns(installed_only=None): -+def _get_patterns(installed_only=None, root=None): - ''' - List all known patterns in repos. - ''' - patterns = {} -- for element in __zypper__.nolock.xml.call('se', '-t', 'pattern').getElementsByTagName('solvable'): -+ for element in __zypper__(root=root).nolock.xml.call('se', '-t', 'pattern').getElementsByTagName('solvable'): - installed = element.getAttribute('status') == 'installed' - if (installed_only and installed) or not installed_only: - patterns[element.getAttribute('name')] = { -@@ -2053,7 +2175,7 @@ def _get_patterns(installed_only=None): - return patterns - - --def list_patterns(refresh=False): -+def list_patterns(refresh=False, root=None): - ''' - List all known patterns from available repos. - -@@ -2062,6 +2184,9 @@ def list_patterns(refresh=False): - If set to False (default) it depends on zypper if a refresh is - executed. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash -@@ -2069,27 +2194,30 @@ def list_patterns(refresh=False): - salt '*' pkg.list_patterns - ''' - if refresh: -- refresh_db() -+ refresh_db(root) - -- return _get_patterns() -+ return _get_patterns(root=root) - - --def list_installed_patterns(): -+def list_installed_patterns(root=None): - ''' - List installed patterns on the system. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash - - salt '*' pkg.list_installed_patterns - ''' -- return _get_patterns(installed_only=True) -+ return _get_patterns(installed_only=True, root=root) - - - def search(criteria, refresh=False, **kwargs): - ''' -- List known packags, available to the system. -+ List known packages, available to the system. - - refresh - force a refresh if set to True. -@@ -2137,6 +2265,9 @@ def search(criteria, refresh=False, **kwargs): - details (bool) - Show version and repository - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash -@@ -2157,8 +2288,11 @@ def search(criteria, refresh=False, **kwargs): - 'not_installed_only': '-u', - 'details': '--details' - } -+ -+ root = kwargs.get('root', None) -+ - if refresh: -- refresh_db() -+ refresh_db(root) - - cmd = ['search'] - if kwargs.get('match') == 'exact': -@@ -2173,7 +2307,7 @@ def search(criteria, refresh=False, **kwargs): - cmd.append(ALLOWED_SEARCH_OPTIONS.get(opt)) - - cmd.append(criteria) -- solvables = __zypper__.nolock.noraise.xml.call(*cmd).getElementsByTagName('solvable') -+ solvables = __zypper__(root=root).nolock.noraise.xml.call(*cmd).getElementsByTagName('solvable') - if not solvables: - raise CommandExecutionError( - 'No packages found matching \'{0}\''.format(criteria) -@@ -2202,7 +2336,7 @@ def _get_first_aggregate_text(node_list): - return '\n'.join(out) - - --def list_products(all=False, refresh=False): -+def list_products(all=False, refresh=False, root=None): - ''' - List all available or installed SUSE products. - -@@ -2214,6 +2348,9 @@ def list_products(all=False, refresh=False): - If set to False (default) it depends on zypper if a refresh is - executed. - -+ root -+ operate on a different root directory. -+ - Includes handling for OEM products, which read the OEM productline file - and overwrite the release value. - -@@ -2225,10 +2362,12 @@ def list_products(all=False, refresh=False): - salt '*' pkg.list_products all=True - ''' - if refresh: -- refresh_db() -+ refresh_db(root) - - ret = list() -- OEM_PATH = "/var/lib/suseRegister/OEM" -+ OEM_PATH = '/var/lib/suseRegister/OEM' -+ if root: -+ OEM_PATH = os.path.join(root, os.path.relpath(OEM_PATH, os.path.sep)) - cmd = list() - if not all: - cmd.append('--disable-repos') -@@ -2236,7 +2375,7 @@ def list_products(all=False, refresh=False): - if not all: - cmd.append('-i') - -- product_list = __zypper__.nolock.xml.call(*cmd).getElementsByTagName('product-list') -+ product_list = __zypper__(root=root).nolock.xml.call(*cmd).getElementsByTagName('product-list') - if not product_list: - return ret # No products found - -@@ -2278,6 +2417,9 @@ def download(*packages, **kwargs): - If set to False (default) it depends on zypper if a refresh is - executed. - -+ root -+ operate on a different root directory. -+ - CLI example: - - .. code-block:: bash -@@ -2288,12 +2430,14 @@ def download(*packages, **kwargs): - if not packages: - raise SaltInvocationError('No packages specified') - -+ root = kwargs.get('root', None) -+ - refresh = kwargs.get('refresh', False) - if refresh: -- refresh_db() -+ refresh_db(root) - - pkg_ret = {} -- for dld_result in __zypper__.xml.call('download', *packages).getElementsByTagName("download-result"): -+ for dld_result in __zypper__(root=root).xml.call('download', *packages).getElementsByTagName("download-result"): - repo = dld_result.getElementsByTagName("repository")[0] - path = dld_result.getElementsByTagName("localfile")[0].getAttribute("path") - pkg_info = { -@@ -2304,7 +2448,7 @@ def download(*packages, **kwargs): - key = _get_first_aggregate_text( - dld_result.getElementsByTagName('name') - ) -- if __salt__['lowpkg.checksum'](pkg_info['path']): -+ if __salt__['lowpkg.checksum'](pkg_info['path'], root=root): - pkg_ret[key] = pkg_info - - if pkg_ret: -@@ -2318,12 +2462,15 @@ def download(*packages, **kwargs): - ) - - --def list_downloaded(): -+def list_downloaded(root=None): - ''' - .. versionadded:: 2017.7.0 - - List prefetched packages downloaded by Zypper in the local disk. - -+ root -+ operate on a different root directory. -+ - CLI example: - - .. code-block:: bash -@@ -2331,6 +2478,8 @@ def list_downloaded(): - salt '*' pkg.list_downloaded - ''' - CACHE_DIR = '/var/cache/zypp/packages/' -+ if root: -+ CACHE_DIR = os.path.join(root, os.path.relpath(CACHE_DIR, os.path.sep)) - - ret = {} - for root, dirnames, filenames in salt.utils.path.os_walk(CACHE_DIR): -@@ -2347,12 +2496,14 @@ def list_downloaded(): - return ret - - --def diff(*paths): -+def diff(*paths, **kwargs): - ''' - Return a formatted diff between current files and original in a package. - NOTE: this function includes all files (configuration and not), but does - not work on binary content. - -+ The root parameter can also be passed via the keyword argument. -+ - :param path: Full path to the installed file - :return: Difference string or raises and exception if examined file is binary. - -@@ -2366,7 +2517,7 @@ def diff(*paths): - - pkg_to_paths = {} - for pth in paths: -- pth_pkg = __salt__['lowpkg.owner'](pth) -+ pth_pkg = __salt__['lowpkg.owner'](pth, **kwargs) - if not pth_pkg: - ret[pth] = os.path.exists(pth) and 'Not managed' or 'N/A' - else: -@@ -2375,7 +2526,7 @@ def diff(*paths): - pkg_to_paths[pth_pkg].append(pth) - - if pkg_to_paths: -- local_pkgs = __salt__['pkg.download'](*pkg_to_paths.keys()) -+ local_pkgs = __salt__['pkg.download'](*pkg_to_paths.keys(), **kwargs) - for pkg, files in six.iteritems(pkg_to_paths): - for path in files: - ret[path] = __salt__['lowpkg.diff']( -@@ -2386,12 +2537,12 @@ def diff(*paths): - return ret - - --def _get_patches(installed_only=False): -+def _get_patches(installed_only=False, root=None): - ''' - List all known patches in repos. - ''' - patches = {} -- for element in __zypper__.nolock.xml.call('se', '-t', 'patch').getElementsByTagName('solvable'): -+ for element in __zypper__(root=root).nolock.xml.call('se', '-t', 'patch').getElementsByTagName('solvable'): - installed = element.getAttribute('status') == 'installed' - if (installed_only and installed) or not installed_only: - patches[element.getAttribute('name')] = { -@@ -2402,7 +2553,7 @@ def _get_patches(installed_only=False): - return patches - - --def list_patches(refresh=False): -+def list_patches(refresh=False, root=None): - ''' - .. versionadded:: 2017.7.0 - -@@ -2413,6 +2564,9 @@ def list_patches(refresh=False): - If set to False (default) it depends on zypper if a refresh is - executed. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash -@@ -2420,33 +2574,39 @@ def list_patches(refresh=False): - salt '*' pkg.list_patches - ''' - if refresh: -- refresh_db() -+ refresh_db(root) - -- return _get_patches() -+ return _get_patches(root=root) - - --def list_installed_patches(): -+def list_installed_patches(root=None): - ''' - .. versionadded:: 2017.7.0 - - List installed advisory patches on the system. - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash - - salt '*' pkg.list_installed_patches - ''' -- return _get_patches(installed_only=True) -+ return _get_patches(installed_only=True, root=root) - - --def list_provides(**kwargs): -+def list_provides(root=None, **kwargs): - ''' - .. versionadded:: 2018.3.0 - - List package provides of installed packages as a dict. - {'': ['', '', ...]} - -+ root -+ operate on a different root directory. -+ - CLI Examples: - - .. code-block:: bash -@@ -2455,7 +2615,10 @@ def list_provides(**kwargs): - ''' - ret = __context__.get('pkg.list_provides') - if not ret: -- cmd = ['rpm', '-qa', '--queryformat', '%{PROVIDES}_|-%{NAME}\n'] -+ cmd = ['rpm'] -+ if root: -+ cmd.extend(['--root', root]) -+ cmd.extend(['-qa', '--queryformat', '%{PROVIDES}_|-%{NAME}\n']) - ret = dict() - for line in __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False).splitlines(): - provide, realname = line.split('_|-') -@@ -2471,7 +2634,7 @@ def list_provides(**kwargs): - return ret - - --def resolve_capabilities(pkgs, refresh, **kwargs): -+def resolve_capabilities(pkgs, refresh=False, root=None, **kwargs): - ''' - .. versionadded:: 2018.3.0 - -@@ -2485,6 +2648,9 @@ def resolve_capabilities(pkgs, refresh, **kwargs): - If set to False (default) it depends on zypper if a refresh is - executed. - -+ root -+ operate on a different root directory. -+ - resolve_capabilities - If this option is set to True the input will be checked if - a package with this name exists. If not, this function will -@@ -2500,7 +2666,7 @@ def resolve_capabilities(pkgs, refresh, **kwargs): - salt '*' pkg.resolve_capabilities resolve_capabilities=True w3m_ssl - ''' - if refresh: -- refresh_db() -+ refresh_db(root) - - ret = list() - for pkg in pkgs: -@@ -2513,12 +2679,12 @@ def resolve_capabilities(pkgs, refresh, **kwargs): - - if kwargs.get('resolve_capabilities', False): - try: -- search(name, match='exact') -+ search(name, root=root, match='exact') - except CommandExecutionError: - # no package this such a name found - # search for a package which provides this name - try: -- result = search(name, provides=True, match='exact') -+ result = search(name, root=root, provides=True, match='exact') - if len(result) == 1: - name = next(iter(result.keys())) - elif len(result) > 1: -diff --git a/salt/states/pkg.py b/salt/states/pkg.py -index 0aca1e0af8..22a97fe98c 100644 ---- a/salt/states/pkg.py -+++ b/salt/states/pkg.py -@@ -241,7 +241,7 @@ def _fulfills_version_spec(versions, oper, desired_version, - return False - - --def _find_unpurge_targets(desired): -+def _find_unpurge_targets(desired, **kwargs): - ''' - Find packages which are marked to be purged but can't yet be removed - because they are dependencies for other installed packages. These are the -@@ -250,7 +250,7 @@ def _find_unpurge_targets(desired): - ''' - return [ - x for x in desired -- if x in __salt__['pkg.list_pkgs'](purge_desired=True) -+ if x in __salt__['pkg.list_pkgs'](purge_desired=True, **kwargs) - ] - - -@@ -265,7 +265,7 @@ def _find_download_targets(name=None, - Inspect the arguments to pkg.downloaded and discover what packages need to - be downloaded. Return a dict of packages to download. - ''' -- cur_pkgs = __salt__['pkg.list_downloaded']() -+ cur_pkgs = __salt__['pkg.list_downloaded'](**kwargs) - if pkgs: - to_download = _repack_pkgs(pkgs, normalize=normalize) - -@@ -383,7 +383,7 @@ def _find_advisory_targets(name=None, - Inspect the arguments to pkg.patch_installed and discover what advisory - patches need to be installed. Return a dict of advisory patches to install. - ''' -- cur_patches = __salt__['pkg.list_installed_patches']() -+ cur_patches = __salt__['pkg.list_installed_patches'](**kwargs) - if advisory_ids: - to_download = advisory_ids - else: -@@ -587,7 +587,7 @@ def _find_install_targets(name=None, - 'minion log.'.format('pkgs' if pkgs - else 'sources')} - -- to_unpurge = _find_unpurge_targets(desired) -+ to_unpurge = _find_unpurge_targets(desired, **kwargs) - else: - if salt.utils.platform.is_windows(): - pkginfo = _get_package_info(name, saltenv=kwargs['saltenv']) -@@ -607,7 +607,7 @@ def _find_install_targets(name=None, - else: - desired = {name: version} - -- to_unpurge = _find_unpurge_targets(desired) -+ to_unpurge = _find_unpurge_targets(desired, **kwargs) - - # FreeBSD pkg supports `openjdk` and `java/openjdk7` package names - origin = bool(re.search('/', name)) -@@ -766,7 +766,8 @@ def _find_install_targets(name=None, - verify_result = __salt__['pkg.verify']( - package_name, - ignore_types=ignore_types, -- verify_options=verify_options -+ verify_options=verify_options, -+ **kwargs - ) - except (CommandExecutionError, SaltInvocationError) as exc: - failed_verify = exc.strerror -@@ -795,7 +796,9 @@ def _find_install_targets(name=None, - verify_result = __salt__['pkg.verify']( - package_name, - ignore_types=ignore_types, -- verify_options=verify_options) -+ verify_options=verify_options, -+ **kwargs -+ ) - except (CommandExecutionError, SaltInvocationError) as exc: - failed_verify = exc.strerror - continue -@@ -1910,7 +1913,8 @@ def installed( - # have caught invalid arguments earlier. - verify_result = __salt__['pkg.verify'](reinstall_pkg, - ignore_types=ignore_types, -- verify_options=verify_options) -+ verify_options=verify_options, -+ **kwargs) - if verify_result: - failed.append(reinstall_pkg) - altered_files[reinstall_pkg] = verify_result -@@ -2098,7 +2102,7 @@ def downloaded(name, - 'package(s): {0}'.format(exc) - return ret - -- new_pkgs = __salt__['pkg.list_downloaded']() -+ new_pkgs = __salt__['pkg.list_downloaded'](**kwargs) - ok, failed = _verify_install(targets, new_pkgs, ignore_epoch=ignore_epoch) - - if failed: -@@ -2974,7 +2978,7 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs): - pkgs, refresh = _resolve_capabilities(pkgs, refresh=refresh, **kwargs) - try: - packages = __salt__['pkg.list_upgrades'](refresh=refresh, **kwargs) -- expected = {pkgname: {'new': pkgver, 'old': __salt__['pkg.version'](pkgname)} -+ expected = {pkgname: {'new': pkgver, 'old': __salt__['pkg.version'](pkgname, **kwargs)} - for pkgname, pkgver in six.iteritems(packages)} - if isinstance(pkgs, list): - packages = [pkg for pkg in packages if pkg in pkgs] -@@ -3156,7 +3160,7 @@ def group_installed(name, skip=None, include=None, **kwargs): - .format(name, exc)) - return ret - -- failed = [x for x in targets if x not in __salt__['pkg.list_pkgs']()] -+ failed = [x for x in targets if x not in __salt__['pkg.list_pkgs'](**kwargs)] - if failed: - ret['comment'] = ( - 'Failed to install the following packages: {0}' -diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py -index 4d5e9eea92..6d8e94aa18 100644 ---- a/salt/states/pkgrepo.py -+++ b/salt/states/pkgrepo.py -@@ -393,10 +393,7 @@ def managed(name, ppa=None, **kwargs): - kwargs.pop(kwarg, None) - - try: -- pre = __salt__['pkg.get_repo']( -- repo, -- ppa_auth=kwargs.get('ppa_auth', None) -- ) -+ pre = __salt__['pkg.get_repo'](repo=repo, **kwargs) - except CommandExecutionError as exc: - ret['result'] = False - ret['comment'] = \ -@@ -512,10 +509,7 @@ def managed(name, ppa=None, **kwargs): - return ret - - try: -- post = __salt__['pkg.get_repo']( -- repo, -- ppa_auth=kwargs.get('ppa_auth', None) -- ) -+ post = __salt__['pkg.get_repo'](repo=repo, **kwargs) - if pre: - for kwarg in sanitizedkwargs: - if post.get(kwarg) != pre.get(kwarg): -@@ -608,9 +602,7 @@ def absent(name, **kwargs): - return ret - - try: -- repo = __salt__['pkg.get_repo']( -- name, ppa_auth=kwargs.get('ppa_auth', None) -- ) -+ repo = __salt__['pkg.get_repo'](name, **kwargs) - except CommandExecutionError as exc: - ret['result'] = False - ret['comment'] = \ -diff --git a/tests/unit/modules/test_rpm_lowpkg.py b/tests/unit/modules/test_rpm_lowpkg.py -index 0a2359ccb2..dc9f52c572 100644 ---- a/tests/unit/modules/test_rpm_lowpkg.py -+++ b/tests/unit/modules/test_rpm_lowpkg.py -@@ -20,6 +20,11 @@ from tests.support.mock import ( - import salt.modules.rpm_lowpkg as rpm - - -+def _called_with_root(mock): -+ cmd = ' '.join(mock.call_args[0][0]) -+ return cmd.startswith('rpm --root /') -+ -+ - @skipIf(NO_MOCK, NO_MOCK_REASON) - class RpmTestCase(TestCase, LoaderModuleMockMixin): - ''' -@@ -28,7 +33,7 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - def setup_loader_modules(self): - return {rpm: {'rpm': MagicMock(return_value=MagicMock)}} - -- # 'list_pkgs' function tests: 1 -+ # 'list_pkgs' function tests: 2 - - def test_list_pkgs(self): - ''' -@@ -37,13 +42,24 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - mock = MagicMock(return_value='') - with patch.dict(rpm.__salt__, {'cmd.run': mock}): - self.assertDictEqual(rpm.list_pkgs(), {}) -+ self.assertFalse(_called_with_root(mock)) -+ -+ def test_list_pkgs_root(self): -+ ''' -+ Test if it list the packages currently installed in a dict, -+ called with root parameter -+ ''' -+ mock = MagicMock(return_value='') -+ with patch.dict(rpm.__salt__, {'cmd.run': mock}): -+ rpm.list_pkgs(root='/') -+ self.assertTrue(_called_with_root(mock)) - -- # 'verify' function tests: 1 -+ # 'verify' function tests: 2 - - def test_verify(self): - ''' -- Test if it runs an rpm -Va on a system, -- and returns the results in a dict -+ Test if it runs an rpm -Va on a system, and returns the -+ results in a dict - ''' - mock = MagicMock(return_value={'stdout': '', - 'stderr': '', -@@ -51,8 +67,22 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - 'pid': 12345}) - with patch.dict(rpm.__salt__, {'cmd.run_all': mock}): - self.assertDictEqual(rpm.verify('httpd'), {}) -+ self.assertFalse(_called_with_root(mock)) -+ -+ def test_verify_root(self): -+ ''' -+ Test if it runs an rpm -Va on a system, and returns the -+ results in a dict, called with root parameter -+ ''' -+ mock = MagicMock(return_value={'stdout': '', -+ 'stderr': '', -+ 'retcode': 0, -+ 'pid': 12345}) -+ with patch.dict(rpm.__salt__, {'cmd.run_all': mock}): -+ rpm.verify('httpd', root='/') -+ self.assertTrue(_called_with_root(mock)) - -- # 'file_list' function tests: 1 -+ # 'file_list' function tests: 2 - - def test_file_list(self): - ''' -@@ -62,8 +92,20 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - with patch.dict(rpm.__salt__, {'cmd.run': mock}): - self.assertDictEqual(rpm.file_list('httpd'), - {'errors': [], 'files': []}) -+ self.assertFalse(_called_with_root(mock)) - -- # 'file_dict' function tests: 1 -+ def test_file_list_root(self): -+ ''' -+ Test if it list the files that belong to a package, using the -+ root parameter. -+ ''' -+ -+ mock = MagicMock(return_value='') -+ with patch.dict(rpm.__salt__, {'cmd.run': mock}): -+ rpm.file_list('httpd', root='/') -+ self.assertTrue(_called_with_root(mock)) -+ -+ # 'file_dict' function tests: 2 - - def test_file_dict(self): - ''' -@@ -73,6 +115,16 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - with patch.dict(rpm.__salt__, {'cmd.run': mock}): - self.assertDictEqual(rpm.file_dict('httpd'), - {'errors': [], 'packages': {}}) -+ self.assertFalse(_called_with_root(mock)) -+ -+ def test_file_dict_root(self): -+ ''' -+ Test if it list the files that belong to a package -+ ''' -+ mock = MagicMock(return_value='') -+ with patch.dict(rpm.__salt__, {'cmd.run': mock}): -+ rpm.file_dict('httpd', root='/') -+ self.assertTrue(_called_with_root(mock)) - - # 'owner' function tests: 1 - -@@ -86,6 +138,7 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - mock = MagicMock(return_value=ret) - with patch.dict(rpm.__salt__, {'cmd.run_stdout': mock}): - self.assertEqual(rpm.owner('/usr/bin/salt-jenkins-build'), '') -+ self.assertFalse(_called_with_root(mock)) - - ret = {'/usr/bin/vim': 'vim-enhanced-7.4.160-1.e17.x86_64', - '/usr/bin/python': 'python-2.7.5-16.e17.x86_64'} -@@ -94,8 +147,22 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - with patch.dict(rpm.__salt__, {'cmd.run_stdout': mock}): - self.assertDictEqual(rpm.owner('/usr/bin/python', '/usr/bin/vim'), - ret) -+ self.assertFalse(_called_with_root(mock)) - -- # 'checksum' function tests: 1 -+ def test_owner_root(self): -+ ''' -+ Test if it return the name of the package that owns the file, -+ using the parameter root. -+ ''' -+ self.assertEqual(rpm.owner(), '') -+ -+ ret = 'file /usr/bin/salt-jenkins-build is not owned by any package' -+ mock = MagicMock(return_value=ret) -+ with patch.dict(rpm.__salt__, {'cmd.run_stdout': mock}): -+ rpm.owner('/usr/bin/salt-jenkins-build', root='/') -+ self.assertTrue(_called_with_root(mock)) -+ -+ # 'checksum' function tests: 2 - - def test_checksum(self): - ''' -@@ -110,6 +177,17 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin): - mock = MagicMock(side_effect=[True, 0, True, 1, False, 0]) - with patch.dict(rpm.__salt__, {'file.file_exists': mock, 'cmd.retcode': mock}): - self.assertDictEqual(rpm.checksum("file1.rpm", "file2.rpm", "file3.rpm"), ret) -+ self.assertFalse(_called_with_root(mock)) -+ -+ def test_checksum_root(self): -+ ''' -+ Test if checksum validate as expected, using the parameter -+ root -+ ''' -+ mock = MagicMock(side_effect=[True, 0]) -+ with patch.dict(rpm.__salt__, {'file.file_exists': mock, 'cmd.retcode': mock}): -+ rpm.checksum("file1.rpm", root='/') -+ self.assertTrue(_called_with_root(mock)) - - def test_version_cmp_rpm(self): - ''' -diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index f586c23fd0..e7474ff777 100644 ---- a/tests/unit/modules/test_zypperpkg.py -+++ b/tests/unit/modules/test_zypperpkg.py -@@ -40,6 +40,9 @@ class ZyppCallMock(object): - return self - - def __call__(self, *args, **kwargs): -+ # If the call is for a configuration modifier, we return self -+ if any(i in kwargs for i in ('no_repo_failure', 'systemd_scope', 'root')): -+ return self - return MagicMock(return_value=self.__return_value)() - - -@@ -925,7 +928,7 @@ Repository 'DUMMY' not found by its alias, number, or URI. - 'pico': '0.1.1', - } - -- def __call__(self): -+ def __call__(self, root=None): - pkgs = self._pkgs.copy() - for target in self._packages: - if self._pkgs.get(target): -@@ -991,10 +994,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. - with zypper_patcher: - zypper.mod_repo(name, **{'url': url}) - self.assertEqual( -- zypper.__zypper__.xml.call.call_args_list, -+ zypper.__zypper__(root=None).xml.call.call_args_list, - [call('ar', url, name)] - ) -- self.assertTrue(zypper.__zypper__.refreshable.xml.call.call_count == 0) -+ self.assertTrue(zypper.__zypper__(root=None).refreshable.xml.call.call_count == 0) - - def test_repo_noadd_nomod_noref(self): - ''' -@@ -1016,8 +1019,8 @@ Repository 'DUMMY' not found by its alias, number, or URI. - self.assertEqual( - out['comment'], - 'Specified arguments did not result in modification of repo') -- self.assertTrue(zypper.__zypper__.xml.call.call_count == 0) -- self.assertTrue(zypper.__zypper__.refreshable.xml.call.call_count == 0) -+ self.assertTrue(zypper.__zypper__(root=None).xml.call.call_count == 0) -+ self.assertTrue(zypper.__zypper__(root=None).refreshable.xml.call.call_count == 0) - - def test_repo_noadd_modbaseurl_ref(self): - ''' -@@ -1045,9 +1048,11 @@ Repository 'DUMMY' not found by its alias, number, or URI. - 'priority': 1, - 'cache': False, - 'keeppackages': False, -- 'type': 'rpm-md'} -- self.assertTrue(zypper.mod_repo.call_count == 2) -- self.assertTrue(zypper.mod_repo.mock_calls[1] == call(name, **expected_params)) -+ 'type': 'rpm-md', -+ 'root': None, -+ } -+ self.assertEqual(zypper.mod_repo.call_count, 2) -+ self.assertEqual(zypper.mod_repo.mock_calls[1], call(name, **expected_params)) - - def test_repo_add_mod_noref(self): - ''' -@@ -1063,10 +1068,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. - with zypper_patcher: - zypper.mod_repo(name, **{'url': url, 'refresh': True}) - self.assertEqual( -- zypper.__zypper__.xml.call.call_args_list, -+ zypper.__zypper__(root=None).xml.call.call_args_list, - [call('ar', url, name)] - ) -- zypper.__zypper__.refreshable.xml.call.assert_called_once_with( -+ zypper.__zypper__(root=None).refreshable.xml.call.assert_called_once_with( - 'mr', '--refresh', name - ) - -@@ -1085,8 +1090,8 @@ Repository 'DUMMY' not found by its alias, number, or URI. - 'salt.modules.zypperpkg', **self.zypper_patcher_config) - with zypper_patcher: - zypper.mod_repo(name, **{'url': url, 'refresh': True}) -- self.assertTrue(zypper.__zypper__.xml.call.call_count == 0) -- zypper.__zypper__.refreshable.xml.call.assert_called_once_with( -+ self.assertTrue(zypper.__zypper__(root=None).xml.call.call_count == 0) -+ zypper.__zypper__(root=None).refreshable.xml.call.assert_called_once_with( - 'mr', '--refresh', name - ) - -@@ -1105,13 +1110,13 @@ Repository 'DUMMY' not found by its alias, number, or URI. - with zypper_patcher: - zypper.mod_repo(name, **{'url': url, 'gpgautoimport': True}) - self.assertEqual( -- zypper.__zypper__.xml.call.call_args_list, -+ zypper.__zypper__(root=None).xml.call.call_args_list, - [ - call('ar', url, name), - call('--gpg-auto-import-keys', 'refresh', name) - ] - ) -- self.assertTrue(zypper.__zypper__.refreshable.xml.call.call_count == 0) -+ self.assertTrue(zypper.__zypper__(root=None).refreshable.xml.call.call_count == 0) - - def test_repo_noadd_nomod_ref(self): - ''' -@@ -1132,10 +1137,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. - with zypper_patcher: - zypper.mod_repo(name, **{'url': url, 'gpgautoimport': True}) - self.assertEqual( -- zypper.__zypper__.xml.call.call_args_list, -+ zypper.__zypper__(root=None).xml.call.call_args_list, - [call('--gpg-auto-import-keys', 'refresh', name)] - ) -- self.assertTrue(zypper.__zypper__.refreshable.xml.call.call_count == 0) -+ self.assertTrue(zypper.__zypper__(root=None).refreshable.xml.call.call_count == 0) - - def test_repo_add_mod_ref(self): - ''' -@@ -1156,13 +1161,13 @@ Repository 'DUMMY' not found by its alias, number, or URI. - **{'url': url, 'refresh': True, 'gpgautoimport': True} - ) - self.assertEqual( -- zypper.__zypper__.xml.call.call_args_list, -+ zypper.__zypper__(root=None).xml.call.call_args_list, - [ - call('ar', url, name), - call('--gpg-auto-import-keys', 'refresh', name) - ] - ) -- zypper.__zypper__.refreshable.xml.call.assert_called_once_with( -+ zypper.__zypper__(root=None).refreshable.xml.call.assert_called_once_with( - '--gpg-auto-import-keys', 'mr', '--refresh', name - ) - -@@ -1188,10 +1193,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. - **{'url': url, 'refresh': True, 'gpgautoimport': True} - ) - self.assertEqual( -- zypper.__zypper__.xml.call.call_args_list, -+ zypper.__zypper__(root=None).xml.call.call_args_list, - [call('--gpg-auto-import-keys', 'refresh', name)] - ) -- zypper.__zypper__.refreshable.xml.call.assert_called_once_with( -+ zypper.__zypper__(root=None).refreshable.xml.call.assert_called_once_with( - '--gpg-auto-import-keys', 'mr', '--refresh', name - ) - -diff --git a/tests/unit/states/test_pkg.py b/tests/unit/states/test_pkg.py -index 42fe6c6867..d30e064167 100644 ---- a/tests/unit/states/test_pkg.py -+++ b/tests/unit/states/test_pkg.py -@@ -46,7 +46,7 @@ class PkgTestCase(TestCase, LoaderModuleMockMixin): - pkgname: pkgver['new'] for pkgname, pkgver in six.iteritems(self.pkgs) - }) - upgrade = MagicMock(return_value=self.pkgs) -- version = MagicMock(side_effect=lambda pkgname: self.pkgs[pkgname]['old']) -+ version = MagicMock(side_effect=lambda pkgname, **_: self.pkgs[pkgname]['old']) - - with patch.dict(pkg.__salt__, - {'pkg.list_upgrades': list_upgrades, -@@ -55,7 +55,6 @@ class PkgTestCase(TestCase, LoaderModuleMockMixin): - - # Run state with test=false - with patch.dict(pkg.__opts__, {'test': False}): -- - ret = pkg.uptodate('dummy', test=True) - self.assertTrue(ret['result']) - self.assertDictEqual(ret['changes'], self.pkgs) -@@ -81,7 +80,7 @@ class PkgTestCase(TestCase, LoaderModuleMockMixin): - pkgname: pkgver['new'] for pkgname, pkgver in six.iteritems(self.pkgs) - }) - upgrade = MagicMock(return_value=self.pkgs) -- version = MagicMock(side_effect=lambda pkgname: pkgs[pkgname]['old']) -+ version = MagicMock(side_effect=lambda pkgname, **_: pkgs[pkgname]['old']) - - with patch.dict(pkg.__salt__, - {'pkg.list_upgrades': list_upgrades, -@@ -160,7 +159,7 @@ class PkgTestCase(TestCase, LoaderModuleMockMixin): - pkgname: pkgver['new'] for pkgname, pkgver in six.iteritems(self.pkgs) - }) - upgrade = MagicMock(return_value={}) -- version = MagicMock(side_effect=lambda pkgname: pkgs[pkgname]['old']) -+ version = MagicMock(side_effect=lambda pkgname, **_: pkgs[pkgname]['old']) - - with patch.dict(pkg.__salt__, - {'pkg.list_upgrades': list_upgrades, --- -2.20.1 - -