mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2017.7' into merge-2017.7-2018.3
Conflicts: - salt/cloud/clouds/openstack.py - salt/daemons/masterapi.py - salt/master.py - salt/modules/gentoo_service.py - salt/pillar/__init__.py - salt/pillar/git_pillar.py - salt/runners/cache.py - salt/runners/git_pillar.py - salt/runners/winrepo.py - salt/utils/docker/__init__.py - salt/utils/gitfs.py
This commit is contained in:
commit
61ab47ee70
19 changed files with 245 additions and 57 deletions
Binary file not shown.
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 109 KiB |
|
@ -5304,11 +5304,10 @@ branch/tag.
|
|||
|
||||
winrepo_branch: winrepo
|
||||
|
||||
ext_pillar:
|
||||
- git:
|
||||
- https://mygitserver/winrepo1.git
|
||||
- https://mygitserver/winrepo2.git:
|
||||
- foo https://mygitserver/winrepo3.git
|
||||
winrepo_remotes:
|
||||
- https://mygitserver/winrepo1.git
|
||||
- https://mygitserver/winrepo2.git:
|
||||
- foo https://mygitserver/winrepo3.git
|
||||
|
||||
.. conf_master:: winrepo_ssl_verify
|
||||
|
||||
|
|
|
@ -76,7 +76,8 @@ def init_git_pillar(opts):
|
|||
opts,
|
||||
opts_dict['git'],
|
||||
per_remote_overrides=git_pillar.PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=git_pillar.PER_REMOTE_ONLY)
|
||||
per_remote_only=git_pillar.PER_REMOTE_ONLY,
|
||||
global_only=git_pillar.GLOBAL_ONLY)
|
||||
ret.append(pillar)
|
||||
except salt.exceptions.FileserverConfigError:
|
||||
if opts.get('git_pillar_verify_config', True):
|
||||
|
|
|
@ -601,7 +601,8 @@ class Master(SMaster):
|
|||
new_opts,
|
||||
repo['git'],
|
||||
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY,
|
||||
global_only=salt.pillar.git_pillar.GLOBAL_ONLY)
|
||||
except salt.exceptions.FileserverConfigError as exc:
|
||||
critical_errors.append(exc.strerror)
|
||||
finally:
|
||||
|
|
|
@ -589,6 +589,15 @@ def _scrub_links(links, name):
|
|||
return ret
|
||||
|
||||
|
||||
def _ulimit_sort(ulimit_val):
|
||||
if isinstance(ulimit_val, list):
|
||||
return sorted(ulimit_val,
|
||||
key=lambda x: (x.get('Name'),
|
||||
x.get('Hard', 0),
|
||||
x.get('Soft', 0)))
|
||||
return ulimit_val
|
||||
|
||||
|
||||
def _size_fmt(num):
|
||||
'''
|
||||
Format bytes as human-readable file sizes
|
||||
|
@ -932,6 +941,9 @@ def compare_containers(first, second, ignore=None):
|
|||
if item == 'Links':
|
||||
val1 = sorted(_scrub_links(val1, first))
|
||||
val2 = sorted(_scrub_links(val2, second))
|
||||
if item == 'Ulimits':
|
||||
val1 = _ulimit_sort(val1)
|
||||
val2 = _ulimit_sort(val2)
|
||||
if val1 != val2:
|
||||
ret.setdefault(conf_dict, {})[item] = {'old': val1, 'new': val2}
|
||||
# Check for optionally-present items that were in the second container
|
||||
|
@ -955,6 +967,9 @@ def compare_containers(first, second, ignore=None):
|
|||
if item == 'Links':
|
||||
val1 = sorted(_scrub_links(val1, first))
|
||||
val2 = sorted(_scrub_links(val2, second))
|
||||
if item == 'Ulimits':
|
||||
val1 = _ulimit_sort(val1)
|
||||
val2 = _ulimit_sort(val2)
|
||||
if val1 != val2:
|
||||
ret.setdefault(conf_dict, {})[item] = {'old': val1, 'new': val2}
|
||||
return ret
|
||||
|
|
|
@ -39,9 +39,9 @@ def __virtual__():
|
|||
'only available on Gentoo/Open-RC systems.')
|
||||
|
||||
|
||||
def _ret_code(cmd):
|
||||
def _ret_code(cmd, ignore_retcode=False):
|
||||
log.debug('executing [{0}]'.format(cmd))
|
||||
sts = __salt__['cmd.retcode'](cmd, python_shell=False)
|
||||
sts = __salt__['cmd.retcode'](cmd, python_shell=False, ignore_retcode=ignore_retcode)
|
||||
return sts
|
||||
|
||||
|
||||
|
@ -270,7 +270,7 @@ def status(name, sig=None):
|
|||
results = {}
|
||||
for service in services:
|
||||
cmd = _service_cmd(service, 'status')
|
||||
results[service] = not _ret_code(cmd)
|
||||
results[service] = not _ret_code(cmd, ignore_retcode=True)
|
||||
if contains_globbing:
|
||||
return results
|
||||
return results[name]
|
||||
|
|
|
@ -900,7 +900,8 @@ class Pillar(object):
|
|||
self.opts,
|
||||
self.ext['git'],
|
||||
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY,
|
||||
global_only=salt.pillar.git_pillar.GLOBAL_ONLY)
|
||||
git_pillar.fetch_remotes()
|
||||
except TypeError:
|
||||
# Handle malformed ext_pillar
|
||||
|
|
|
@ -347,6 +347,7 @@ from salt.ext import six
|
|||
|
||||
PER_REMOTE_OVERRIDES = ('env', 'root', 'ssl_verify', 'refspecs')
|
||||
PER_REMOTE_ONLY = ('name', 'mountpoint')
|
||||
GLOBAL_ONLY = ('base', 'branch')
|
||||
|
||||
# Set up logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -385,7 +386,8 @@ def ext_pillar(minion_id, pillar, *repos): # pylint: disable=unused-argument
|
|||
opts,
|
||||
repos,
|
||||
per_remote_overrides=PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=PER_REMOTE_ONLY)
|
||||
per_remote_only=PER_REMOTE_ONLY,
|
||||
global_only=GLOBAL_ONLY)
|
||||
if __opts__.get('__role') == 'minion':
|
||||
# If masterless, fetch the remotes. We'll need to remove this once
|
||||
# we make the minion daemon able to run standalone.
|
||||
|
|
|
@ -355,7 +355,8 @@ def clear_git_lock(role, remote=None, **kwargs):
|
|||
__opts__,
|
||||
ext_pillar['git'],
|
||||
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY,
|
||||
global_only=salt.pillar.git_pillar.GLOBAL_ONLY)
|
||||
git_objects.append(obj)
|
||||
elif role == 'winrepo':
|
||||
winrepo_dir = __opts__['winrepo_dir']
|
||||
|
@ -371,6 +372,7 @@ def clear_git_lock(role, remote=None, **kwargs):
|
|||
remotes,
|
||||
per_remote_overrides=salt.runners.winrepo.PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=salt.runners.winrepo.PER_REMOTE_ONLY,
|
||||
global_only=salt.runners.winrepo.GLOBAL_ONLY,
|
||||
cache_root=base_dir)
|
||||
git_objects.append(obj)
|
||||
else:
|
||||
|
|
|
@ -164,6 +164,20 @@ def file_list(saltenv='base', backend=None):
|
|||
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
.. note:
|
||||
Keep in mind that executing this function spawns a new process,
|
||||
separate from the master. This means that if the fileserver
|
||||
configuration has been changed in some way since the master has been
|
||||
restarted (e.g. if :conf_master:`fileserver_backend`,
|
||||
:conf_master:`gitfs_remotes`, :conf_master:`hgfs_remotes`, etc. have
|
||||
been updated), then the results of this runner will not accurately
|
||||
reflect what files are available to minions.
|
||||
|
||||
When in doubt, use :py:func:`cp.list_master
|
||||
<salt.modules.cp.list_master>` to see what files the minion can see,
|
||||
and always remember to restart the salt-master daemon when updating
|
||||
the fileserver configuration.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -196,6 +210,20 @@ def symlink_list(saltenv='base', backend=None):
|
|||
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
.. note:
|
||||
Keep in mind that executing this function spawns a new process,
|
||||
separate from the master. This means that if the fileserver
|
||||
configuration has been changed in some way since the master has been
|
||||
restarted (e.g. if :conf_master:`fileserver_backend`,
|
||||
:conf_master:`gitfs_remotes`, :conf_master:`hgfs_remotes`, etc. have
|
||||
been updated), then the results of this runner will not accurately
|
||||
reflect what symlinks are available to minions.
|
||||
|
||||
When in doubt, use :py:func:`cp.list_master_symlinks
|
||||
<salt.modules.cp.list_master_symlinks>` to see what symlinks the minion
|
||||
can see, and always remember to restart the salt-master daemon when
|
||||
updating the fileserver configuration.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -228,6 +256,20 @@ def dir_list(saltenv='base', backend=None):
|
|||
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
.. note:
|
||||
Keep in mind that executing this function spawns a new process,
|
||||
separate from the master. This means that if the fileserver
|
||||
configuration has been changed in some way since the master has been
|
||||
restarted (e.g. if :conf_master:`fileserver_backend`,
|
||||
:conf_master:`gitfs_remotes`, :conf_master:`hgfs_remotes`, etc. have
|
||||
been updated), then the results of this runner will not accurately
|
||||
reflect what dirs are available to minions.
|
||||
|
||||
When in doubt, use :py:func:`cp.list_master_dirs
|
||||
<salt.modules.cp.list_master_dirs>` to see what dirs the minion can see,
|
||||
and always remember to restart the salt-master daemon when updating
|
||||
the fileserver configuration.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
|
|
@ -70,7 +70,8 @@ def update(branch=None, repo=None):
|
|||
__opts__,
|
||||
pillar_conf,
|
||||
per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY)
|
||||
per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY,
|
||||
global_only=salt.pillar.git_pillar.GLOBAL_ONLY)
|
||||
for remote in pillar.remotes:
|
||||
# Skip this remote if it doesn't match the search criteria
|
||||
if branch is not None:
|
||||
|
|
|
@ -37,6 +37,7 @@ PER_REMOTE_OVERRIDES = ('ssl_verify', 'refspecs')
|
|||
# salt.utils.gitfs.PER_REMOTE_ONLY for this value, so this is mainly for
|
||||
# runners and other modules that import salt.runners.winrepo.
|
||||
PER_REMOTE_ONLY = salt.utils.gitfs.PER_REMOTE_ONLY
|
||||
GLOBAL_ONLY = ('branch',)
|
||||
|
||||
|
||||
def genrepo(opts=None, fire_event=True):
|
||||
|
@ -164,7 +165,8 @@ def update_git_repos(opts=None, clean=False, masterless=False):
|
|||
|
||||
ret = {}
|
||||
for remotes, base_dir in winrepo_cfg:
|
||||
if not any((salt.utils.gitfs.HAS_GITPYTHON, salt.utils.gitfs.HAS_PYGIT2)):
|
||||
if not any((salt.utils.gitfs.GITPYTHON_VERSION,
|
||||
salt.utils.gitfs.PYGIT2_VERSION)):
|
||||
# Use legacy code
|
||||
winrepo_result = {}
|
||||
for remote_info in remotes:
|
||||
|
@ -217,6 +219,7 @@ def update_git_repos(opts=None, clean=False, masterless=False):
|
|||
remotes,
|
||||
per_remote_overrides=PER_REMOTE_OVERRIDES,
|
||||
per_remote_only=PER_REMOTE_ONLY,
|
||||
global_only=GLOBAL_ONLY,
|
||||
cache_root=base_dir)
|
||||
winrepo.fetch_remotes()
|
||||
# Since we're not running update(), we need to manually call
|
||||
|
|
|
@ -696,7 +696,7 @@ def extracted(name,
|
|||
# True
|
||||
# >>> os.path.isfile('/tmp/foo.txt/')
|
||||
# False
|
||||
name = name.rstrip('/')
|
||||
name = name.rstrip(os.sep)
|
||||
if os.path.isfile(name):
|
||||
ret['comment'] = '{0} exists and is not a directory'.format(name)
|
||||
return ret
|
||||
|
@ -729,6 +729,11 @@ def extracted(name,
|
|||
)
|
||||
return ret
|
||||
|
||||
if if_missing is not None and os.path.exists(if_missing):
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Path {0} exists'.format(if_missing)
|
||||
return ret
|
||||
|
||||
if user or group:
|
||||
if salt.utils.platform.is_windows():
|
||||
ret['comment'] = \
|
||||
|
@ -1511,7 +1516,7 @@ def extracted(name,
|
|||
if not if_missing:
|
||||
# If is_missing was used, and both a) the archive had never been
|
||||
# extracted, and b) the path referred to by if_missing exists, then
|
||||
# enforce_missing would contain paths of top_levle dirs/files that
|
||||
# enforce_missing would contain paths of top_level dirs/files that
|
||||
# _would_ have been extracted. Since if_missing can be used as a
|
||||
# semaphore to conditionally extract, we don't want to make this a
|
||||
# case where the state fails, so we only fail the state if
|
||||
|
|
|
@ -1564,14 +1564,14 @@ def running(name,
|
|||
.. code-block:: yaml
|
||||
|
||||
foo:
|
||||
dockerng.running:
|
||||
docker_container.running:
|
||||
- image: bar/baz:latest
|
||||
- ulimits: nofile=1024:1024,nproc=60
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
foo:
|
||||
dockerng.running:
|
||||
docker_container.running:
|
||||
- image: bar/baz:latest
|
||||
- ulimits:
|
||||
- nofile=1024:1024
|
||||
|
|
|
@ -8,6 +8,7 @@ input as formatted by states.
|
|||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
|
||||
|
@ -183,7 +184,7 @@ def translate_input(translator,
|
|||
of that tuple will have their translation skipped. Optionally,
|
||||
skip_translate can be set to True to skip *all* translation.
|
||||
'''
|
||||
kwargs = salt.utils.args.clean_kwargs(**kwargs)
|
||||
kwargs = copy.deepcopy(salt.utils.clean_kwargs(**kwargs))
|
||||
invalid = {}
|
||||
collisions = []
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ VALID_REF_TYPES = _DEFAULT_MASTER_OPTS['gitfs_ref_types']
|
|||
# Optional per-remote params that can only be used on a per-remote basis, and
|
||||
# thus do not have defaults in salt/config.py.
|
||||
PER_REMOTE_ONLY = ('name',)
|
||||
# Params which are global only and cannot be overridden for a single remote.
|
||||
GLOBAL_ONLY = ()
|
||||
|
||||
SYMLINK_RECURSE_DEPTH = 100
|
||||
|
||||
# Auth support (auth params can be global or per-remote, too)
|
||||
|
@ -357,7 +360,7 @@ class GitProvider(object):
|
|||
salt.utils.url.strip_proto(saltenv_ptr['mountpoint'])
|
||||
|
||||
for key, val in six.iteritems(self.conf):
|
||||
if key not in PER_SALTENV_PARAMS:
|
||||
if key not in PER_SALTENV_PARAMS and not hasattr(self, key):
|
||||
setattr(self, key, val)
|
||||
|
||||
for key in PER_SALTENV_PARAMS:
|
||||
|
@ -973,13 +976,13 @@ class GitProvider(object):
|
|||
'''
|
||||
Resolve dynamically-set branch
|
||||
'''
|
||||
if self.branch == '__env__':
|
||||
if self.role == 'git_pillar' and self.branch == '__env__':
|
||||
target = self.opts.get('pillarenv') \
|
||||
or self.opts.get('saltenv') \
|
||||
or 'base'
|
||||
return self.opts['{0}_base'.format(self.role)] \
|
||||
return self.base \
|
||||
if target == 'base' \
|
||||
else target
|
||||
else six.text_type(target)
|
||||
return self.branch
|
||||
|
||||
def get_tree(self, tgt_env):
|
||||
|
@ -1021,7 +1024,7 @@ class GitProvider(object):
|
|||
try:
|
||||
self.branch, self.url = self.id.split(None, 1)
|
||||
except ValueError:
|
||||
self.branch = self.opts['{0}_branch'.format(self.role)]
|
||||
self.branch = self.conf['branch']
|
||||
self.url = self.id
|
||||
else:
|
||||
self.url = self.id
|
||||
|
@ -2026,8 +2029,8 @@ class GitBase(object):
|
|||
Base class for gitfs/git_pillar
|
||||
'''
|
||||
def __init__(self, opts, remotes=None, per_remote_overrides=(),
|
||||
per_remote_only=PER_REMOTE_ONLY, git_providers=None,
|
||||
cache_root=None, init_remotes=True):
|
||||
per_remote_only=PER_REMOTE_ONLY, global_only=GLOBAL_ONLY,
|
||||
git_providers=None, cache_root=None, init_remotes=True):
|
||||
'''
|
||||
IMPORTANT: If specifying a cache_root, understand that this is also
|
||||
where the remotes will be cloned. A non-default cache_root is only
|
||||
|
@ -2085,10 +2088,12 @@ class GitBase(object):
|
|||
self.init_remotes(
|
||||
remotes if remotes is not None else [],
|
||||
per_remote_overrides,
|
||||
per_remote_only)
|
||||
per_remote_only,
|
||||
global_only)
|
||||
|
||||
def init_remotes(self, remotes, per_remote_overrides=(),
|
||||
per_remote_only=PER_REMOTE_ONLY):
|
||||
per_remote_only=PER_REMOTE_ONLY,
|
||||
global_only=GLOBAL_ONLY):
|
||||
'''
|
||||
Initialize remotes
|
||||
'''
|
||||
|
@ -2121,7 +2126,9 @@ class GitBase(object):
|
|||
failhard(self.role)
|
||||
|
||||
per_remote_defaults = {}
|
||||
for param in override_params:
|
||||
global_values = set(override_params)
|
||||
global_values.update(set(global_only))
|
||||
for param in global_values:
|
||||
key = '{0}_{1}'.format(self.role, param)
|
||||
if key not in self.opts:
|
||||
log.critical(
|
||||
|
@ -2967,8 +2974,7 @@ class GitPillar(GitBase):
|
|||
if repo.env:
|
||||
env = repo.env
|
||||
else:
|
||||
base_branch = self.opts['{0}_base'.format(self.role)]
|
||||
env = 'base' if repo.branch == base_branch else repo.branch
|
||||
env = 'base' if repo.branch == repo.base else repo.branch
|
||||
if repo._mountpoint:
|
||||
if self.link_mountpoint(repo):
|
||||
self.pillar_dirs[repo.linkdir] = env
|
||||
|
@ -3095,6 +3101,9 @@ class WinRepo(GitBase):
|
|||
Functionality specific to the winrepo runner
|
||||
'''
|
||||
role = 'winrepo'
|
||||
# Need to define this in case we try to reference it before checking
|
||||
# out the repos.
|
||||
winrepo_dirs = {}
|
||||
|
||||
def checkout(self):
|
||||
'''
|
||||
|
|
|
@ -754,6 +754,35 @@ class DockerTestCase(TestCase, LoaderModuleMockMixin):
|
|||
ret = docker_mod.compare_containers('container1', 'container2')
|
||||
self.assertEqual(ret, {})
|
||||
|
||||
def test_compare_container_ulimits_order(self):
|
||||
'''
|
||||
Test comparing two containers when the order of the Ulimits HostConfig
|
||||
values are different, but the values are the same.
|
||||
'''
|
||||
def _inspect_container_effect(id_):
|
||||
return {
|
||||
'container1': {'Config': {},
|
||||
'HostConfig': {
|
||||
'Ulimits': [
|
||||
{u'Hard': -1, u'Soft': -1, u'Name': u'core'},
|
||||
{u'Hard': 65536, u'Soft': 65536, u'Name': u'nofile'}
|
||||
]
|
||||
}},
|
||||
'container2': {'Config': {},
|
||||
'HostConfig': {
|
||||
'Ulimits': [
|
||||
{u'Hard': 65536, u'Soft': 65536, u'Name': u'nofile'},
|
||||
{u'Hard': -1, u'Soft': -1, u'Name': u'core'}
|
||||
]
|
||||
}},
|
||||
}[id_]
|
||||
|
||||
inspect_container_mock = MagicMock(side_effect=_inspect_container_effect)
|
||||
|
||||
with patch.object(docker_mod, 'inspect_container', inspect_container_mock):
|
||||
ret = docker_mod.compare_container('container1', 'container2')
|
||||
self.assertEqual(ret, {})
|
||||
|
||||
def test_resolve_tag(self):
|
||||
'''
|
||||
Test the resolve_tag function. It runs docker.insect_image on the image
|
||||
|
|
|
@ -151,7 +151,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.start('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name start', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name start',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
|
||||
def test_stop(self):
|
||||
'''
|
||||
|
@ -160,7 +162,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.stop('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name stop', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name stop',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
|
||||
def test_restart(self):
|
||||
'''
|
||||
|
@ -169,7 +173,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.restart('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name restart', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name restart',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
|
||||
def test_reload_(self):
|
||||
'''
|
||||
|
@ -178,7 +184,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.reload_('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name reload', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name reload',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
|
||||
def test_zap(self):
|
||||
'''
|
||||
|
@ -187,7 +195,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.zap('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name zap', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name zap',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
|
||||
def test_status(self):
|
||||
'''
|
||||
|
@ -201,25 +211,33 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
mock = MagicMock(return_value=0)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertTrue(gentoo_service.status('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name status', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name status',
|
||||
ignore_retcode=True,
|
||||
python_shell=False)
|
||||
|
||||
# service is not running
|
||||
mock = MagicMock(return_value=1)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.status('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name status', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name status',
|
||||
ignore_retcode=True,
|
||||
python_shell=False)
|
||||
|
||||
# service is stopped
|
||||
mock = MagicMock(return_value=3)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.status('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name status', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name status',
|
||||
ignore_retcode=True,
|
||||
python_shell=False)
|
||||
|
||||
# service has crashed
|
||||
mock = MagicMock(return_value=32)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': mock}):
|
||||
self.assertFalse(gentoo_service.status('name'))
|
||||
mock.assert_called_once_with('/etc/init.d/name status', python_shell=False)
|
||||
mock.assert_called_once_with('/etc/init.d/name status',
|
||||
ignore_retcode=True,
|
||||
python_shell=False)
|
||||
|
||||
def test_enable(self):
|
||||
'''
|
||||
|
@ -228,7 +246,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
rc_update_mock = MagicMock(return_value=0)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.enable('name'))
|
||||
rc_update_mock.assert_called_once_with('rc-update add name', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update add name',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# move service from 'l1' to 'l2' runlevel
|
||||
|
@ -238,8 +258,12 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.enable('name', runlevels='l2'))
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l1', python_shell=False),
|
||||
call('rc-update add name l2', python_shell=False)])
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False),
|
||||
call('rc-update add name l2',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)])
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# requested levels are the same as the current ones
|
||||
|
@ -260,7 +284,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.enable('name', runlevels=['l2', 'l1']))
|
||||
rc_update_mock.assert_called_once_with('rc-update add name l2', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update add name l2',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# remove service from 'l1' runlevel
|
||||
|
@ -269,15 +295,21 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.enable('name', runlevels=['l2']))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# move service from 'l2' add to 'l3', leaving at l1
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.enable('name', runlevels=['l1', 'l3']))
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l2', python_shell=False),
|
||||
call('rc-update add name l3', python_shell=False)])
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l2',
|
||||
ignore_retcode=False,
|
||||
python_shell=False),
|
||||
call('rc-update add name l3',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)])
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# remove from l1, l3, and add to l2, l4, and leave at l5
|
||||
|
@ -286,15 +318,21 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.enable('name', runlevels=['l2', 'l4', 'l5']))
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l1 l3', python_shell=False),
|
||||
call('rc-update add name l2 l4', python_shell=False)])
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l1 l3',
|
||||
ignore_retcode=False,
|
||||
python_shell=False),
|
||||
call('rc-update add name l2 l4',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)])
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# rc-update failed
|
||||
rc_update_mock = MagicMock(return_value=1)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertFalse(gentoo_service.enable('name'))
|
||||
rc_update_mock.assert_called_once_with('rc-update add name', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update add name',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# move service delete failed
|
||||
|
@ -303,7 +341,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertFalse(gentoo_service.enable('name', runlevels='l2'))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# move service delete succeeds. add fails
|
||||
|
@ -312,8 +352,12 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertFalse(gentoo_service.enable('name', runlevels='l2'))
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l1', python_shell=False),
|
||||
call('rc-update add name l2', python_shell=False)])
|
||||
rc_update_mock.assert_has_calls([call('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False),
|
||||
call('rc-update add name l2',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)])
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
def test_disable(self):
|
||||
|
@ -323,7 +367,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
rc_update_mock = MagicMock(return_value=0)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.disable('name'))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# disable service
|
||||
|
@ -334,6 +380,7 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.disable('name', runlevels='l1'))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
|
@ -344,6 +391,7 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.disable('name', runlevels=['l1']))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
|
@ -354,6 +402,7 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.disable('name', runlevels=['l1']))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
|
@ -373,6 +422,7 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertTrue(gentoo_service.disable('name', runlevels=['l1', 'l3']))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1 l3',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
|
@ -380,7 +430,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
rc_update_mock = MagicMock(return_value=1)
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertFalse(gentoo_service.disable('name'))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# move service delete failed
|
||||
|
@ -389,7 +441,9 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.run': level_list_mock}):
|
||||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertFalse(gentoo_service.disable('name', runlevels='l1'))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1', python_shell=False)
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
# move service delete succeeds. add fails
|
||||
|
@ -399,6 +453,7 @@ class GentooServicesTestCase(TestCase, LoaderModuleMockMixin):
|
|||
with patch.dict(gentoo_service.__salt__, {'cmd.retcode': rc_update_mock}):
|
||||
self.assertFalse(gentoo_service.disable('name', runlevels=['l1', 'l3']))
|
||||
rc_update_mock.assert_called_once_with('rc-update delete name l1 l3',
|
||||
ignore_retcode=False,
|
||||
python_shell=False)
|
||||
rc_update_mock.reset_mock()
|
||||
|
||||
|
|
|
@ -203,3 +203,25 @@ class ArchiveTestCase(TestCase, LoaderModuleMockMixin):
|
|||
enforce_toplevel=False,
|
||||
keep=True)
|
||||
self.assertEqual(ret['changes']['extracted_files'], 'stderr')
|
||||
|
||||
def test_extracted_when_if_missing_path_exists(self):
|
||||
'''
|
||||
When if_missing exists, we should exit without making any changes.
|
||||
|
||||
NOTE: We're not mocking the __salt__ dunder because if we actually run
|
||||
any functions from that dunder, we're doing something wrong. So, in
|
||||
those cases we'll just let it raise a KeyError and cause the test to
|
||||
fail.
|
||||
'''
|
||||
name = if_missing = '/tmp/foo'
|
||||
source = 'salt://foo.bar.tar'
|
||||
with patch.object(os.path, 'exists', MagicMock(return_value=True)):
|
||||
ret = archive.extracted(
|
||||
name,
|
||||
source=source,
|
||||
if_missing=if_missing)
|
||||
self.assertTrue(ret['result'], ret)
|
||||
self.assertEqual(
|
||||
ret['comment'],
|
||||
'Path {0} exists'.format(if_missing)
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue