mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #52528 from Ch3LL/merge-2019.2
[2019.2] Merge forward from 2018.3 to 2019.2
This commit is contained in:
commit
cc0cd5ddde
15 changed files with 193 additions and 123 deletions
|
@ -119,7 +119,8 @@ def need_deployment():
|
|||
if dstat.st_uid != euid:
|
||||
# Attack detected, try again
|
||||
need_deployment()
|
||||
if dstat.st_mode != 16832:
|
||||
# AIX has non-POSIX bit 0o240700, isolate to 0o40700
|
||||
if dstat.st_mode & ~65536 != 16832:
|
||||
# Attack detected
|
||||
need_deployment()
|
||||
# If SUDOing then also give the super user group write permissions
|
||||
|
|
|
@ -298,7 +298,12 @@ def list_(narrow=None,
|
|||
|
||||
result = __salt__['cmd.run_all'](cmd, python_shell=False)
|
||||
|
||||
if result['retcode'] != 0:
|
||||
# Chocolatey introduced Enhanced Exit Codes starting with version 0.10.12
|
||||
# Exit Code 2 means there were no results, but is not a failure
|
||||
# This may start to effect other functions in the future as Chocolatey
|
||||
# moves more functions to this new paradigm
|
||||
# https://github.com/chocolatey/choco/issues/1758
|
||||
if result['retcode'] not in [0, 2]:
|
||||
err = 'Running chocolatey failed: {0}'.format(result['stdout'])
|
||||
raise CommandExecutionError(err)
|
||||
|
||||
|
|
|
@ -1168,7 +1168,7 @@ def list_repos(**kwargs): # pylint: disable=unused-argument
|
|||
return repos
|
||||
|
||||
|
||||
def get_repo(alias, **kwargs): # pylint: disable=unused-argument
|
||||
def get_repo(repo, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Display a repo from the ``/etc/opkg/*.conf``
|
||||
|
||||
|
@ -1176,19 +1176,19 @@ def get_repo(alias, **kwargs): # pylint: disable=unused-argument
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' pkg.get_repo alias
|
||||
salt '*' pkg.get_repo repo
|
||||
'''
|
||||
repos = list_repos()
|
||||
|
||||
if repos:
|
||||
for source in six.itervalues(repos):
|
||||
for sub in source:
|
||||
if sub['name'] == alias:
|
||||
if sub['name'] == repo:
|
||||
return sub
|
||||
return {}
|
||||
|
||||
|
||||
def _del_repo_from_file(alias, filepath):
|
||||
def _del_repo_from_file(repo, filepath):
|
||||
'''
|
||||
Remove a repo from filepath
|
||||
'''
|
||||
|
@ -1201,30 +1201,30 @@ def _del_repo_from_file(alias, filepath):
|
|||
if line.startswith('#'):
|
||||
line = line[1:]
|
||||
cols = salt.utils.args.shlex_split(line.strip())
|
||||
if alias != cols[1]:
|
||||
if repo != cols[1]:
|
||||
output.append(salt.utils.stringutils.to_str(line))
|
||||
with salt.utils.files.fopen(filepath, 'w') as fhandle:
|
||||
fhandle.writelines(output)
|
||||
|
||||
|
||||
def _add_new_repo(alias, uri, compressed, enabled=True):
|
||||
def _add_new_repo(repo, uri, compressed, enabled=True):
|
||||
'''
|
||||
Add a new repo entry
|
||||
'''
|
||||
repostr = '# ' if not enabled else ''
|
||||
repostr += 'src/gz ' if compressed else 'src '
|
||||
if ' ' in alias:
|
||||
repostr += '"' + alias + '" '
|
||||
if ' ' in repo:
|
||||
repostr += '"' + repo + '" '
|
||||
else:
|
||||
repostr += alias + ' '
|
||||
repostr += repo + ' '
|
||||
repostr += uri + '\n'
|
||||
conffile = os.path.join(OPKG_CONFDIR, alias + '.conf')
|
||||
conffile = os.path.join(OPKG_CONFDIR, repo + '.conf')
|
||||
|
||||
with salt.utils.files.fopen(conffile, 'a') as fhandle:
|
||||
fhandle.write(salt.utils.stringutils.to_str(repostr))
|
||||
|
||||
|
||||
def _mod_repo_in_file(alias, repostr, filepath):
|
||||
def _mod_repo_in_file(repo, repostr, filepath):
|
||||
'''
|
||||
Replace a repo entry in filepath with repostr
|
||||
'''
|
||||
|
@ -1234,7 +1234,7 @@ def _mod_repo_in_file(alias, repostr, filepath):
|
|||
cols = salt.utils.args.shlex_split(
|
||||
salt.utils.stringutils.to_unicode(line).strip()
|
||||
)
|
||||
if alias not in cols:
|
||||
if repo not in cols:
|
||||
output.append(line)
|
||||
else:
|
||||
output.append(salt.utils.stringutils.to_str(repostr + '\n'))
|
||||
|
@ -1242,7 +1242,7 @@ def _mod_repo_in_file(alias, repostr, filepath):
|
|||
fhandle.writelines(output)
|
||||
|
||||
|
||||
def del_repo(alias, **kwargs): # pylint: disable=unused-argument
|
||||
def del_repo(repo, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Delete a repo from ``/etc/opkg/*.conf``
|
||||
|
||||
|
@ -1253,21 +1253,22 @@ def del_repo(alias, **kwargs): # pylint: disable=unused-argument
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' pkg.del_repo alias
|
||||
salt '*' pkg.del_repo repo
|
||||
'''
|
||||
refresh = salt.utils.data.is_true(kwargs.get('refresh', True))
|
||||
repos = list_repos()
|
||||
if repos:
|
||||
deleted_from = dict()
|
||||
for repo in repos:
|
||||
source = repos[repo][0]
|
||||
if source['name'] == alias:
|
||||
for repository in repos:
|
||||
source = repos[repository][0]
|
||||
if source['name'] == repo:
|
||||
deleted_from[source['file']] = 0
|
||||
_del_repo_from_file(alias, source['file'])
|
||||
_del_repo_from_file(repo, source['file'])
|
||||
|
||||
if deleted_from:
|
||||
ret = ''
|
||||
for repo in repos:
|
||||
source = repos[repo][0]
|
||||
for repository in repos:
|
||||
source = repos[repository][0]
|
||||
if source['file'] in deleted_from:
|
||||
deleted_from[source['file']] += 1
|
||||
for repo_file, count in six.iteritems(deleted_from):
|
||||
|
@ -1279,22 +1280,22 @@ def del_repo(alias, **kwargs): # pylint: disable=unused-argument
|
|||
os.remove(repo_file)
|
||||
except OSError:
|
||||
pass
|
||||
ret += msg.format(alias, repo_file)
|
||||
# explicit refresh after a repo is deleted
|
||||
refresh_db()
|
||||
ret += msg.format(repo, repo_file)
|
||||
if refresh:
|
||||
refresh_db()
|
||||
return ret
|
||||
|
||||
return "Repo {0} doesn't exist in the opkg repo lists".format(alias)
|
||||
return "Repo {0} doesn't exist in the opkg repo lists".format(repo)
|
||||
|
||||
|
||||
def mod_repo(alias, **kwargs):
|
||||
def mod_repo(repo, **kwargs):
|
||||
'''
|
||||
Modify one or more values for a repo. If the repo does not exist, it will
|
||||
be created, so long as uri is defined.
|
||||
|
||||
The following options are available to modify a repo definition:
|
||||
|
||||
alias
|
||||
repo
|
||||
alias by which opkg refers to the repo.
|
||||
uri
|
||||
the URI to the repo.
|
||||
|
@ -1310,8 +1311,8 @@ def mod_repo(alias, **kwargs):
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' pkg.mod_repo alias uri=http://new/uri
|
||||
salt '*' pkg.mod_repo alias enabled=False
|
||||
salt '*' pkg.mod_repo repo uri=http://new/uri
|
||||
salt '*' pkg.mod_repo repo enabled=False
|
||||
'''
|
||||
repos = list_repos()
|
||||
found = False
|
||||
|
@ -1319,9 +1320,9 @@ def mod_repo(alias, **kwargs):
|
|||
if 'uri' in kwargs:
|
||||
uri = kwargs['uri']
|
||||
|
||||
for repo in repos:
|
||||
source = repos[repo][0]
|
||||
if source['name'] == alias:
|
||||
for repository in repos:
|
||||
source = repos[repository][0]
|
||||
if source['name'] == repo:
|
||||
found = True
|
||||
repostr = ''
|
||||
if 'enabled' in kwargs and not kwargs['enabled']:
|
||||
|
@ -1330,13 +1331,13 @@ def mod_repo(alias, **kwargs):
|
|||
repostr += 'src/gz ' if kwargs['compressed'] else 'src'
|
||||
else:
|
||||
repostr += 'src/gz' if source['compressed'] else 'src'
|
||||
repo_alias = kwargs['alias'] if 'alias' in kwargs else alias
|
||||
repo_alias = kwargs['alias'] if 'alias' in kwargs else repo
|
||||
if ' ' in repo_alias:
|
||||
repostr += ' "{0}"'.format(repo_alias)
|
||||
else:
|
||||
repostr += ' {0}'.format(repo_alias)
|
||||
repostr += ' {0}'.format(kwargs['uri'] if 'uri' in kwargs else source['uri'])
|
||||
_mod_repo_in_file(alias, repostr, source['file'])
|
||||
_mod_repo_in_file(repo, repostr, source['file'])
|
||||
elif uri and source['uri'] == uri:
|
||||
raise CommandExecutionError(
|
||||
'Repository \'{0}\' already exists as \'{1}\'.'.format(uri, source['name']))
|
||||
|
@ -1345,12 +1346,12 @@ def mod_repo(alias, **kwargs):
|
|||
# Need to add a new repo
|
||||
if 'uri' not in kwargs:
|
||||
raise CommandExecutionError(
|
||||
'Repository \'{0}\' not found and no URI passed to create one.'.format(alias))
|
||||
'Repository \'{0}\' not found and no URI passed to create one.'.format(repo))
|
||||
# If compressed is not defined, assume True
|
||||
compressed = kwargs['compressed'] if 'compressed' in kwargs else True
|
||||
# If enabled is not defined, assume True
|
||||
enabled = kwargs['enabled'] if 'enabled' in kwargs else True
|
||||
_add_new_repo(alias, kwargs['uri'], compressed, enabled)
|
||||
_add_new_repo(repo, kwargs['uri'], compressed, enabled)
|
||||
|
||||
if 'refresh' in kwargs:
|
||||
refresh_db()
|
||||
|
|
|
@ -205,22 +205,23 @@ def get_zone():
|
|||
Returns:
|
||||
str: Timezone in unix format
|
||||
|
||||
Raises:
|
||||
CommandExecutionError: If timezone could not be gathered
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' timezone.get_zone
|
||||
'''
|
||||
cmd = ['tzutil', '/g']
|
||||
res = __salt__['cmd.run_all'](cmd, python_shell=False)
|
||||
if res['retcode'] or not res['stdout']:
|
||||
raise CommandExecutionError('tzutil encountered an error getting '
|
||||
'timezone',
|
||||
info=res)
|
||||
return mapper.get_unix(res['stdout'].lower(), 'Unknown')
|
||||
win_zone = __utils__['reg.read_value'](
|
||||
hive='HKLM',
|
||||
key='SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation',
|
||||
vname='TimeZoneKeyName')['vdata']
|
||||
# Some data may have null characters. We only need the first portion up to
|
||||
# the first null character. See the following:
|
||||
# https://github.com/saltstack/salt/issues/51940
|
||||
# https://stackoverflow.com/questions/27716746/hklm-system-currentcontrolset-control-timezoneinformation-timezonekeyname-corrup
|
||||
if '\0' in win_zone:
|
||||
win_zone = win_zone.split('\0')[0]
|
||||
return mapper.get_unix(win_zone.lower(), 'Unknown')
|
||||
|
||||
|
||||
def get_offset():
|
||||
|
|
|
@ -777,6 +777,11 @@ def extracted(name,
|
|||
ret['comment'] = exc.strerror
|
||||
return ret
|
||||
|
||||
if not source_match:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Invalid source "{0}"'.format(source)
|
||||
return ret
|
||||
|
||||
urlparsed_source = _urlparse(source_match)
|
||||
urlparsed_scheme = urlparsed_source.scheme
|
||||
urlparsed_path = os.path.join(
|
||||
|
|
|
@ -2775,7 +2775,7 @@ def managed(name,
|
|||
reset=win_perms_reset)
|
||||
except CommandExecutionError as exc:
|
||||
if exc.strerror.startswith('Path not found'):
|
||||
ret['changes'] = {name: 'will be created'}
|
||||
ret['changes']['newfile'] = name
|
||||
|
||||
if isinstance(ret['changes'], tuple):
|
||||
ret['result'], ret['comment'] = ret['changes']
|
||||
|
|
|
@ -316,9 +316,8 @@ class IPCClient(object):
|
|||
if self.stream is None:
|
||||
with salt.utils.asynchronous.current_ioloop(self.io_loop):
|
||||
self.stream = IOStream(
|
||||
socket.socket(sock_type, socket.SOCK_STREAM),
|
||||
socket.socket(sock_type, socket.SOCK_STREAM)
|
||||
)
|
||||
|
||||
try:
|
||||
log.trace('IPCClient: Connecting to socket: %s', self.socket_path)
|
||||
yield self.stream.connect(sock_addr)
|
||||
|
|
|
@ -1611,11 +1611,19 @@ class Pygit2(GitProvider):
|
|||
'''
|
||||
Clean stale local refs so they don't appear as fileserver environments
|
||||
'''
|
||||
try:
|
||||
if pygit2.GIT_FETCH_PRUNE:
|
||||
# Don't need to clean anything, pygit2 can do it by itself
|
||||
return []
|
||||
except AttributeError:
|
||||
# However, only in 0.26.2 and newer
|
||||
pass
|
||||
if self.credentials is not None:
|
||||
log.debug(
|
||||
'pygit2 does not support detecting stale refs for '
|
||||
'authenticated remotes, saltenvs will not reflect '
|
||||
'branches/tags removed from remote \'%s\'', self.id
|
||||
'The installed version of pygit2 (%s) does not support '
|
||||
'detecting stale refs for authenticated remotes, saltenvs '
|
||||
'will not reflect branches/tags removed from remote \'%s\'',
|
||||
PYGIT2_VERSION, self.id
|
||||
)
|
||||
return []
|
||||
return super(Pygit2, self).clean_stale_refs()
|
||||
|
@ -1721,6 +1729,11 @@ class Pygit2(GitProvider):
|
|||
else:
|
||||
if self.credentials is not None:
|
||||
origin.credentials = self.credentials
|
||||
try:
|
||||
fetch_kwargs['prune'] = pygit2.GIT_FETCH_PRUNE
|
||||
except AttributeError:
|
||||
# pruning only available in pygit2 >= 0.26.2
|
||||
pass
|
||||
try:
|
||||
fetch_results = origin.fetch(**fetch_kwargs)
|
||||
except GitError as exc:
|
||||
|
@ -2573,7 +2586,8 @@ class GitBase(object):
|
|||
LIBGIT2_VERSION
|
||||
)
|
||||
)
|
||||
if not salt.utils.path.which('git'):
|
||||
if not getattr(pygit2, 'GIT_FETCH_PRUNE', False) \
|
||||
and not salt.utils.path.which('git'):
|
||||
errors.append(
|
||||
'The git command line utility is required when using the '
|
||||
'\'pygit2\' {0}_provider.'.format(self.role)
|
||||
|
|
|
@ -45,6 +45,14 @@ def _load_libcrypto():
|
|||
# two checks below
|
||||
lib = glob.glob('/opt/local/lib/libcrypto.so*') + glob.glob('/opt/tools/lib/libcrypto.so*')
|
||||
lib = lib[0] if len(lib) > 0 else None
|
||||
if not lib and salt.utils.platform.is_aix():
|
||||
if os.path.isdir('/opt/salt/lib'):
|
||||
# preference for Salt installed fileset
|
||||
lib = glob.glob('/opt/salt/lib/libcrypto.so*')
|
||||
lib = lib[0] if len(lib) > 0 else None
|
||||
else:
|
||||
lib = glob.glob('/opt/freeware/lib/libcrypto.so*')
|
||||
lib = lib[0] if len(lib) > 0 else None
|
||||
if lib:
|
||||
return cdll.LoadLibrary(lib)
|
||||
raise OSError('Cannot locate OpenSSL libcrypto')
|
||||
|
|
|
@ -8,12 +8,16 @@ from tests.support.case import ModuleCase
|
|||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext import six
|
||||
import salt.utils.platform
|
||||
|
||||
|
||||
class StdTest(ModuleCase):
|
||||
'''
|
||||
Test standard client calls
|
||||
'''
|
||||
def setUp(self):
|
||||
self.TIMEOUT = 600 if salt.utils.platform.is_windows() else 10
|
||||
|
||||
def test_cli(self):
|
||||
'''
|
||||
Test cli function
|
||||
|
@ -69,6 +73,7 @@ class StdTest(ModuleCase):
|
|||
'minion',
|
||||
'test.arg',
|
||||
['foo', 'bar', 'baz'],
|
||||
timeout=self.TIMEOUT,
|
||||
kwarg={'qux': 'quux'}
|
||||
)
|
||||
data = ret['minion']['ret']
|
||||
|
@ -84,6 +89,7 @@ class StdTest(ModuleCase):
|
|||
'minion',
|
||||
'test.arg_type',
|
||||
['a', 1],
|
||||
timeout=self.TIMEOUT,
|
||||
kwarg={'outer': {'a': terrible_yaml_string},
|
||||
'inner': 'value'}
|
||||
)
|
||||
|
@ -94,7 +100,9 @@ class StdTest(ModuleCase):
|
|||
self.assertIn(six.text_type.__name__, data['kwargs']['inner'])
|
||||
|
||||
def test_full_return_kwarg(self):
|
||||
ret = self.client.cmd('minion', 'test.ping', full_return=True)
|
||||
ret = self.client.cmd(
|
||||
'minion', 'test.ping', full_return=True, timeout=self.TIMEOUT,
|
||||
)
|
||||
for mid, data in ret.items():
|
||||
self.assertIn('retcode', data)
|
||||
|
||||
|
@ -107,8 +115,10 @@ class StdTest(ModuleCase):
|
|||
],
|
||||
kwarg={
|
||||
'quux': 'Quux',
|
||||
})
|
||||
|
||||
},
|
||||
timeout=self.TIMEOUT,
|
||||
)
|
||||
self.assertEqual(ret['minion'], {
|
||||
'args': ['foo'],
|
||||
'kwargs': {
|
||||
|
|
|
@ -9,12 +9,15 @@ from tests.support.case import ModuleCase
|
|||
|
||||
# Import salt libs
|
||||
import salt.utils.files
|
||||
import salt.utils.platform
|
||||
|
||||
|
||||
class StdTest(ModuleCase):
|
||||
'''
|
||||
Test standard client calls
|
||||
'''
|
||||
def setUp(self):
|
||||
self.TIMEOUT = 600 if salt.utils.platform.is_windows() else 10
|
||||
|
||||
def test_cli(self):
|
||||
'''
|
||||
|
@ -159,7 +162,8 @@ class StdTest(ModuleCase):
|
|||
ret = self.client.cmd(
|
||||
'minion,ghostminion',
|
||||
'test.ping',
|
||||
tgt_type='list'
|
||||
tgt_type='list',
|
||||
timeout=self.TIMEOUT
|
||||
)
|
||||
self.assertIn('minion', ret)
|
||||
self.assertIn('ghostminion', ret)
|
||||
|
|
|
@ -111,35 +111,72 @@ class MineTest(ModuleCase):
|
|||
['grains.items']
|
||||
)
|
||||
)
|
||||
# Smoke testing that grains should now exist in the mine
|
||||
ret_grains = self.run_function(
|
||||
'mine.get',
|
||||
['minion', 'grains.items']
|
||||
)
|
||||
self.assertEqual(ret_grains['minion']['id'], 'minion')
|
||||
self.assertTrue(
|
||||
self.run_function(
|
||||
'mine.send',
|
||||
['test.arg', 'foo=bar', 'fnord=roscivs'],
|
||||
)
|
||||
)
|
||||
ret_args = self.run_function(
|
||||
'mine.get',
|
||||
['minion', 'test.arg']
|
||||
)
|
||||
expected = {
|
||||
'minion': {
|
||||
'args': [],
|
||||
'kwargs': {
|
||||
'fnord': 'roscivs',
|
||||
'foo': 'bar',
|
||||
},
|
||||
},
|
||||
}
|
||||
# Smoke testing that test.arg exists in the mine
|
||||
self.assertDictEqual(ret_args, expected)
|
||||
self.assertTrue(
|
||||
self.run_function(
|
||||
'mine.send',
|
||||
['test.echo', 'foo']
|
||||
)
|
||||
)
|
||||
ret_grains = self.run_function(
|
||||
'mine.get',
|
||||
['minion', 'grains.items']
|
||||
)
|
||||
self.assertEqual(ret_grains['minion']['id'], 'minion')
|
||||
ret_echo = self.run_function(
|
||||
'mine.get',
|
||||
['minion', 'test.echo']
|
||||
)
|
||||
# Smoke testing that we were also able to set test.echo in the mine
|
||||
self.assertEqual(ret_echo['minion'], 'foo')
|
||||
self.assertTrue(
|
||||
self.run_function(
|
||||
'mine.delete',
|
||||
['grains.items']
|
||||
['test.arg']
|
||||
)
|
||||
)
|
||||
ret_grains_deleted = self.run_function(
|
||||
ret_arg_deleted = self.run_function(
|
||||
'mine.get',
|
||||
['minion', 'grains.items']
|
||||
['minion', 'test.arg']
|
||||
)
|
||||
# Now comes the real test - did we obliterate test.arg from the mine?
|
||||
# We could assert this a different way, but there shouldn't be any
|
||||
# other tests that are setting this mine value, so this should
|
||||
# definitely avoid any race conditions.
|
||||
self.assertFalse(
|
||||
ret_arg_deleted.get('minion', {})
|
||||
.get('kwargs', {})
|
||||
.get('fnord', None) == 'roscivs',
|
||||
'{} contained "fnord":"roscivs", which should be gone'.format(
|
||||
ret_arg_deleted,
|
||||
)
|
||||
)
|
||||
self.assertEqual(ret_grains_deleted.get('minion', None), None)
|
||||
ret_echo_stays = self.run_function(
|
||||
'mine.get',
|
||||
['minion', 'test.echo']
|
||||
)
|
||||
# Of course, one more health check - we want targeted removal.
|
||||
# This isn't horseshoes or hand grenades - test.arg should go away
|
||||
# but test.echo should still be available.
|
||||
self.assertEqual(ret_echo_stays['minion'], 'foo')
|
||||
|
|
|
@ -13,7 +13,7 @@ import time
|
|||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.helpers import with_tempdir
|
||||
from tests.support.helpers import with_tempdir, flaky
|
||||
from tests.support.unit import skipIf
|
||||
from tests.support.paths import BASE_FILES, TMP, TMP_PILLAR_TREE
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
|
@ -86,6 +86,7 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
_reline(destpath)
|
||||
destpath = os.path.join(BASE_FILES, 'testappend', 'secondif')
|
||||
_reline(destpath)
|
||||
cls.TIMEOUT = 600 if salt.utils.platform.is_windows() else 10
|
||||
|
||||
def test_show_highstate(self):
|
||||
'''
|
||||
|
@ -1478,7 +1479,9 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
https://github.com/saltstack/salt/issues/22370
|
||||
'''
|
||||
|
||||
state_run = self.run_function('state.sls', mods='requisites.onfail_multiple')
|
||||
state_run = self.run_function('state.sls',
|
||||
mods='requisites.onfail_multiple',
|
||||
timeout=self.TIMEOUT)
|
||||
|
||||
retcode = state_run['cmd_|-c_|-echo itworked_|-run']['changes']['retcode']
|
||||
self.assertEqual(retcode, 0)
|
||||
|
@ -1678,7 +1681,9 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'''
|
||||
|
||||
# Only run the state once and keep the return data
|
||||
state_run = self.run_function('state.sls', mods='requisites.listen_names')
|
||||
state_run = self.run_function('state.sls',
|
||||
mods='requisites.listen_names',
|
||||
timeout=self.TIMEOUT)
|
||||
self.assertIn('test_|-listener_service_|-nginx_|-mod_watch', state_run)
|
||||
self.assertIn('test_|-listener_service_|-crond_|-mod_watch', state_run)
|
||||
|
||||
|
@ -1762,6 +1767,7 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
with salt.utils.files.fopen(testfile, 'a'):
|
||||
pass
|
||||
|
||||
@flaky
|
||||
def test_retry_option_eventual_success(self):
|
||||
'''
|
||||
test a state with the retry option that should return True after at least 4 retry attmempt
|
||||
|
@ -1911,12 +1917,12 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'''
|
||||
self._add_runtime_pillar(pillar={'test': True})
|
||||
testfile = os.path.join(TMP, 'testfile')
|
||||
comment = 'The file {0} is set to be changed'.format(testfile)
|
||||
comment = 'The file {0} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.'.format(testfile)
|
||||
ret = self.run_function('state.sls', ['core'])
|
||||
|
||||
for key, val in ret.items():
|
||||
self.assertEqual(val['comment'], comment)
|
||||
self.assertEqual(val['changes'], {})
|
||||
self.assertEqual(val['changes'], {'newfile': testfile})
|
||||
|
||||
def test_state_sls_id_test_state_test_post_run(self):
|
||||
'''
|
||||
|
@ -1948,8 +1954,8 @@ class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
for key, val in ret.items():
|
||||
self.assertEqual(
|
||||
val['comment'],
|
||||
'The file {0} is set to be changed'.format(file_name))
|
||||
self.assertEqual(val['changes'], {})
|
||||
'The file {0} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.'.format(file_name))
|
||||
self.assertEqual(val['changes'], {'newfile': file_name})
|
||||
|
||||
def test_state_sls_id_test_true_post_run(self):
|
||||
'''
|
||||
|
|
|
@ -62,7 +62,7 @@ class SSHStateTest(SSHCase):
|
|||
ret = self.run_function('state.sls_id', ['ssh-file-test', SSH_SLS,
|
||||
'test=True'])
|
||||
self._check_dict_ret(ret=ret, val='comment',
|
||||
exp_ret='The file /tmp/test is set to be changed')
|
||||
exp_ret='The file /tmp/test is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.')
|
||||
|
||||
# check state.sls_id without test=True
|
||||
ret = self.run_function('state.sls_id', ['ssh-file-test', SSH_SLS])
|
||||
|
|
|
@ -7,7 +7,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
|
||||
# Import Salt Libs
|
||||
import salt.modules.win_timezone as win_timezone
|
||||
from salt.exceptions import CommandExecutionError
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.mock import MagicMock, patch
|
||||
|
@ -26,31 +26,26 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
|
|||
|
||||
def test_get_zone(self):
|
||||
'''
|
||||
Test if it get current timezone (i.e. Asia/Calcutta)
|
||||
Test if it gets current timezone (i.e. Asia/Calcutta)
|
||||
'''
|
||||
mock_read_ok = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': 'India Standard Time'})
|
||||
mock_read = MagicMock(side_effect=[{'vdata': 'India Standard Time'},
|
||||
{'vdata': 'Indian Standard Time'}])
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read_ok}):
|
||||
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
|
||||
self.assertEqual(win_timezone.get_zone(), 'Asia/Calcutta')
|
||||
|
||||
mock_read_error = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': 'Indian Standard Time'})
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read_error}):
|
||||
self.assertEqual(win_timezone.get_zone(), 'Unknown')
|
||||
|
||||
mock_read_fatal = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 1,
|
||||
'stderr': '',
|
||||
'stdout': ''})
|
||||
def test_get_zone_null_terminated(self):
|
||||
'''
|
||||
Test if it handles instances where the registry contains null values
|
||||
'''
|
||||
mock_read = MagicMock(side_effect=[
|
||||
{'vdata': 'India Standard Time\0\0\0\0'},
|
||||
{'vdata': 'Indian Standard Time\0\0some more junk data\0\0'}])
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read_fatal}):
|
||||
self.assertRaises(CommandExecutionError, win_timezone.get_zone)
|
||||
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
|
||||
self.assertEqual(win_timezone.get_zone(), 'Asia/Calcutta')
|
||||
self.assertEqual(win_timezone.get_zone(), 'Unknown')
|
||||
|
||||
# 'get_offset' function tests: 1
|
||||
|
||||
|
@ -58,16 +53,9 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
|
|||
'''
|
||||
Test if it get current numeric timezone offset from UCT (i.e. +0530)
|
||||
'''
|
||||
# time = ('(UTC+05:30) Chennai, Kolkata, Mumbai, \
|
||||
# New Delhi\nIndia Standard Time')
|
||||
# mock_cmd = MagicMock(side_effect=['India Standard Time', time])
|
||||
# with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
|
||||
mock_read = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': 'India Standard Time'})
|
||||
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
|
||||
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
|
||||
self.assertEqual(win_timezone.get_offset(), '+0530')
|
||||
|
||||
# 'get_zonecode' function tests: 1
|
||||
|
@ -76,12 +64,9 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
|
|||
'''
|
||||
Test if it get current timezone (i.e. PST, MDT, etc)
|
||||
'''
|
||||
mock_read = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': 'India Standard Time'})
|
||||
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
|
||||
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
|
||||
self.assertEqual(win_timezone.get_zonecode(), 'IST')
|
||||
|
||||
# 'set_zone' function tests: 1
|
||||
|
@ -90,17 +75,14 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
|
|||
'''
|
||||
Test if it unlinks, then symlinks /etc/localtime to the set timezone.
|
||||
'''
|
||||
mock_write = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': ''})
|
||||
mock_read = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': 'India Standard Time'})
|
||||
mock_cmd = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': ''})
|
||||
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_write}), \
|
||||
patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_cmd}), \
|
||||
patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
|
||||
|
||||
self.assertTrue(win_timezone.set_zone('Asia/Calcutta'))
|
||||
|
||||
|
@ -112,12 +94,9 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
|
|||
the one set in /etc/localtime. Returns True if they match,
|
||||
and False if not. Mostly useful for running state checks.
|
||||
'''
|
||||
mock_read = MagicMock(return_value={'pid': 78,
|
||||
'retcode': 0,
|
||||
'stderr': '',
|
||||
'stdout': 'India Standard Time'})
|
||||
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
|
||||
|
||||
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
|
||||
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
|
||||
self.assertTrue(win_timezone.zone_compare('Asia/Calcutta'))
|
||||
|
||||
# 'get_hwclock' function tests: 1
|
||||
|
|
Loading…
Add table
Reference in a new issue