mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge branch '2016.11' into fix-cron-identifier
This commit is contained in:
commit
df73a4c051
@ -303,6 +303,20 @@ option on the Salt master.
|
||||
|
||||
master_port: 4506
|
||||
|
||||
.. conf_minion:: publish_port
|
||||
|
||||
``publish_port``
|
||||
---------------
|
||||
|
||||
Default: ``4505``
|
||||
|
||||
The port of the master publish server, this needs to coincide with the publish_port
|
||||
option on the Salt master.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
publish_port: 4505
|
||||
|
||||
.. conf_minion:: user
|
||||
|
||||
``user``
|
||||
|
@ -237,7 +237,7 @@ class SyncClientMixin(object):
|
||||
|
||||
def low(self, fun, low, print_event=True, full_return=False):
|
||||
'''
|
||||
Check for deprecated usage and allow until Salt Oxygen.
|
||||
Check for deprecated usage and allow until Salt Fluorine.
|
||||
'''
|
||||
msg = []
|
||||
if 'args' in low:
|
||||
@ -248,7 +248,7 @@ class SyncClientMixin(object):
|
||||
low['kwarg'] = low.pop('kwargs')
|
||||
|
||||
if msg:
|
||||
salt.utils.warn_until('Oxygen', ' '.join(msg))
|
||||
salt.utils.warn_until('Fluorine', ' '.join(msg))
|
||||
|
||||
return self._low(fun, low, print_event=print_event, full_return=full_return)
|
||||
|
||||
|
@ -3764,8 +3764,15 @@ def get_managed(
|
||||
parsed_scheme = urlparsed_source.scheme
|
||||
parsed_path = os.path.join(
|
||||
urlparsed_source.netloc, urlparsed_source.path).rstrip(os.sep)
|
||||
unix_local_source = parsed_scheme in ('file', '')
|
||||
|
||||
if parsed_scheme and parsed_scheme.lower() in 'abcdefghijklmnopqrstuvwxyz':
|
||||
if unix_local_source:
|
||||
sfn = parsed_path
|
||||
if not os.path.exists(sfn):
|
||||
msg = 'Local file source {0} does not exist'.format(sfn)
|
||||
return '', {}, msg
|
||||
|
||||
if parsed_scheme and parsed_scheme.lower() in string.ascii_lowercase:
|
||||
parsed_path = ':'.join([parsed_scheme, parsed_path])
|
||||
parsed_scheme = 'file'
|
||||
|
||||
@ -3773,9 +3780,10 @@ def get_managed(
|
||||
source_sum = __salt__['cp.hash_file'](source, saltenv)
|
||||
if not source_sum:
|
||||
return '', {}, 'Source file {0} not found'.format(source)
|
||||
elif not source_hash and parsed_scheme == 'file':
|
||||
elif not source_hash and unix_local_source:
|
||||
source_sum = _get_local_file_source_sum(parsed_path)
|
||||
elif not source_hash and source.startswith(os.sep):
|
||||
# This should happen on Windows
|
||||
source_sum = _get_local_file_source_sum(source)
|
||||
else:
|
||||
if not skip_verify:
|
||||
@ -4650,21 +4658,22 @@ def manage_file(name,
|
||||
if source_sum and ('hsum' in source_sum):
|
||||
source_sum['hsum'] = source_sum['hsum'].lower()
|
||||
|
||||
if source and not sfn:
|
||||
# File is not present, cache it
|
||||
sfn = __salt__['cp.cache_file'](source, saltenv)
|
||||
if source:
|
||||
if not sfn:
|
||||
return _error(
|
||||
ret, 'Source file \'{0}\' not found'.format(source))
|
||||
htype = source_sum.get('hash_type', __opts__['hash_type'])
|
||||
# Recalculate source sum now that file has been cached
|
||||
source_sum = {
|
||||
'hash_type': htype,
|
||||
'hsum': get_hash(sfn, form=htype)
|
||||
}
|
||||
# File is not present, cache it
|
||||
sfn = __salt__['cp.cache_file'](source, saltenv)
|
||||
if not sfn:
|
||||
return _error(
|
||||
ret, 'Source file \'{0}\' not found'.format(source))
|
||||
htype = source_sum.get('hash_type', __opts__['hash_type'])
|
||||
# Recalculate source sum now that file has been cached
|
||||
source_sum = {
|
||||
'hash_type': htype,
|
||||
'hsum': get_hash(sfn, form=htype)
|
||||
}
|
||||
|
||||
if keep_mode:
|
||||
if _urlparse(source).scheme in ('salt', 'file') \
|
||||
or source.startswith('/'):
|
||||
if _urlparse(source).scheme in ('salt', 'file', ''):
|
||||
try:
|
||||
mode = __salt__['cp.stat_file'](source, saltenv=saltenv, octal=True)
|
||||
except Exception as exc:
|
||||
@ -4694,7 +4703,7 @@ def manage_file(name,
|
||||
# source, and we are not skipping checksum verification, then
|
||||
# verify that it matches the specified checksum.
|
||||
if not skip_verify \
|
||||
and _urlparse(source).scheme not in ('salt', ''):
|
||||
and _urlparse(source).scheme != 'salt':
|
||||
dl_sum = get_hash(sfn, source_sum['hash_type'])
|
||||
if dl_sum != source_sum['hsum']:
|
||||
ret['comment'] = (
|
||||
@ -4859,8 +4868,6 @@ def manage_file(name,
|
||||
group=group, mode=dir_mode)
|
||||
|
||||
if source:
|
||||
# It is a new file, set the diff accordingly
|
||||
ret['changes']['diff'] = 'New file'
|
||||
# Apply the new file
|
||||
if not sfn:
|
||||
sfn = __salt__['cp.cache_file'](source, saltenv)
|
||||
@ -4884,6 +4891,8 @@ def manage_file(name,
|
||||
)
|
||||
ret['result'] = False
|
||||
return ret
|
||||
# It is a new file, set the diff accordingly
|
||||
ret['changes']['diff'] = 'New file'
|
||||
if not os.path.isdir(contain_dir):
|
||||
if makedirs:
|
||||
_set_mode_and_make_dirs(name, dir_mode, mode, user, group)
|
||||
|
@ -1070,8 +1070,8 @@ def build_routes(iface, **settings):
|
||||
log.debug("IPv4 routes:\n{0}".format(opts4))
|
||||
log.debug("IPv6 routes:\n{0}".format(opts6))
|
||||
|
||||
routecfg = template.render(routes=opts4)
|
||||
routecfg6 = template.render(routes=opts6)
|
||||
routecfg = template.render(routes=opts4, iface=iface)
|
||||
routecfg6 = template.render(routes=opts6, iface=iface)
|
||||
|
||||
if settings['test']:
|
||||
routes = _read_temp(routecfg)
|
||||
|
@ -194,6 +194,7 @@ def upgrade_available(name, **kwargs):
|
||||
# Refresh before looking for the latest version available,
|
||||
# same default as latest_version
|
||||
refresh = salt.utils.is_true(kwargs.get('refresh', True))
|
||||
|
||||
# if latest_version returns blank, the latest version is already installed or
|
||||
# their is no package definition. This is a salt standard which could be improved.
|
||||
return latest_version(name, saltenv=saltenv, refresh=refresh) != ''
|
||||
@ -313,10 +314,9 @@ def version(*names, **kwargs):
|
||||
refresh (bool): Refresh package metadata. Default ``False``.
|
||||
|
||||
Returns:
|
||||
str: version string when a single packge is specified.
|
||||
str: version string when a single package is specified.
|
||||
dict: The package name(s) with the installed versions.
|
||||
|
||||
|
||||
.. code-block:: cfg
|
||||
{['<version>', '<version>', ]} OR
|
||||
{'<package name>': ['<version>', '<version>', ]}
|
||||
@ -330,13 +330,13 @@ def version(*names, **kwargs):
|
||||
|
||||
'''
|
||||
# Standard is return empty string even if not a valid name
|
||||
# TODO: Look at returning an error accross all platforms with
|
||||
# TODO: Look at returning an error across all platforms with
|
||||
# CommandExecutionError(msg,info={'errors': errors })
|
||||
# available_pkgs = get_repo_data(saltenv).get('repo')
|
||||
# for name in names:
|
||||
# if name in available_pkgs:
|
||||
# ret[name] = installed_pkgs.get(name, '')
|
||||
#
|
||||
|
||||
saltenv = kwargs.get('saltenv', 'base')
|
||||
installed_pkgs = list_pkgs(saltenv=saltenv, refresh=kwargs.get('refresh', False))
|
||||
|
||||
@ -643,7 +643,7 @@ def _get_repo_details(saltenv):
|
||||
else:
|
||||
winrepo_source_dir = __opts__['winrepo_source_dir']
|
||||
# winrepo_source_dir = __opts__['winrepo_source_dir']
|
||||
winrepo_source_dir = __opts__['winrepo_source_dir']
|
||||
|
||||
dirs = [__opts__['cachedir'], 'files', saltenv]
|
||||
url_parts = _urlparse(winrepo_source_dir)
|
||||
dirs.append(url_parts.netloc)
|
||||
@ -1616,6 +1616,8 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
||||
cached_pkg = cached_pkg.replace('/', '\\')
|
||||
cache_path, _ = os.path.split(cached_pkg)
|
||||
|
||||
# os.path.expandvars is not required as we run everything through cmd.exe /s /c
|
||||
|
||||
# Get uninstall flags
|
||||
uninstall_flags = pkginfo[target].get('uninstall_flags', '')
|
||||
|
||||
@ -1626,7 +1628,9 @@ def remove(name=None, pkgs=None, version=None, **kwargs):
|
||||
# Compute msiexec string
|
||||
use_msiexec, msiexec = _get_msiexec(pkginfo[target].get('msiexec', False))
|
||||
cmd_shell = os.getenv('ComSpec', '{0}\\system32\\cmd.exe'.format(os.getenv('WINDIR')))
|
||||
# Build Scheduled Task Parameters
|
||||
|
||||
# Build cmd and arguments
|
||||
# cmd and arguments must be separated for use with the task scheduler
|
||||
if use_msiexec:
|
||||
# Check if uninstaller is set to {guid}, if not we assume its a remote msi file.
|
||||
# which has already been downloaded.
|
||||
|
@ -142,6 +142,17 @@ def get_printout(out, opts=None, **kwargs):
|
||||
# See Issue #29796 for more information.
|
||||
out = opts['output']
|
||||
|
||||
# Handle setting the output when --static is passed.
|
||||
if not out and opts.get('static'):
|
||||
if opts.get('output'):
|
||||
out = opts['output']
|
||||
elif opts.get('fun', '').split('.')[0] == 'state':
|
||||
# --static doesn't have an output set at this point, but if we're
|
||||
# running a state function and "out" hasn't already been set, we
|
||||
# should set the out variable to "highstate". Otherwise state runs
|
||||
# are set to "nested" below. See Issue #44556 for more information.
|
||||
out = 'highstate'
|
||||
|
||||
if out == 'text':
|
||||
out = 'txt'
|
||||
elif out is None or out == '':
|
||||
|
@ -1605,6 +1605,9 @@ def managed(name,
|
||||
'name': name,
|
||||
'result': True}
|
||||
|
||||
if not name:
|
||||
return _error(ret, 'Destination file name is required')
|
||||
|
||||
if mode is not None and salt.utils.is_windows():
|
||||
return _error(ret, 'The \'mode\' option is not supported on Windows')
|
||||
|
||||
@ -1755,8 +1758,6 @@ def managed(name,
|
||||
ret['comment'] = 'Error while applying template on contents'
|
||||
return ret
|
||||
|
||||
if not name:
|
||||
return _error(ret, 'Must provide name to file.exists')
|
||||
user = _test_owner(kwargs, user=user)
|
||||
if salt.utils.is_windows():
|
||||
if group is not None:
|
||||
|
@ -696,7 +696,7 @@ def edited_conf(name, lxc_conf=None, lxc_conf_unset=None):
|
||||
# to keep this function around and cannot officially remove it. Progress of
|
||||
# the new function will be tracked in https://github.com/saltstack/salt/issues/35523
|
||||
salt.utils.warn_until(
|
||||
'Oxygen',
|
||||
'Fluorine',
|
||||
'This state is unsuitable for setting parameters that appear more '
|
||||
'than once in an LXC config file, or parameters which must appear in '
|
||||
'a certain order (such as when configuring more than one network '
|
||||
|
@ -5,5 +5,6 @@
|
||||
/{{route.netmask}}
|
||||
{%- endif -%}
|
||||
{%- if route.gateway %} via {{route.gateway}}
|
||||
{%- else %} dev {{iface}}
|
||||
{%- endif %}
|
||||
{% endfor -%}
|
||||
|
@ -1115,10 +1115,10 @@ def format_call(fun,
|
||||
continue
|
||||
extra[key] = copy.deepcopy(value)
|
||||
|
||||
# We'll be showing errors to the users until Salt Oxygen comes out, after
|
||||
# We'll be showing errors to the users until Salt Fluorine comes out, after
|
||||
# which, errors will be raised instead.
|
||||
warn_until(
|
||||
'Oxygen',
|
||||
'Fluorine',
|
||||
'It\'s time to start raising `SaltInvocationError` instead of '
|
||||
'returning warnings',
|
||||
# Let's not show the deprecation warning on the console, there's no
|
||||
@ -1155,7 +1155,7 @@ def format_call(fun,
|
||||
'{0}. If you were trying to pass additional data to be used '
|
||||
'in a template context, please populate \'context\' with '
|
||||
'\'key: value\' pairs. Your approach will work until Salt '
|
||||
'Oxygen is out.{1}'.format(
|
||||
'Fluorine is out.{1}'.format(
|
||||
msg,
|
||||
'' if 'full' not in ret else ' Please update your state files.'
|
||||
)
|
||||
|
@ -26,6 +26,16 @@ REMOTE_PROTOS = ('http', 'https', 'ftp', 'swift', 's3')
|
||||
VALID_PROTOS = ('salt', 'file') + REMOTE_PROTOS
|
||||
|
||||
|
||||
def __clean_tmp(tmp):
|
||||
'''
|
||||
Remove temporary files
|
||||
'''
|
||||
try:
|
||||
salt.utils.rm_rf(tmp)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def guess_archive_type(name):
|
||||
'''
|
||||
Guess an archive type (tar, zip, or rar) by its file extension
|
||||
@ -93,7 +103,15 @@ def copyfile(source, dest, backup_mode='', cachedir=''):
|
||||
fstat = os.stat(dest)
|
||||
except OSError:
|
||||
pass
|
||||
shutil.move(tgt, dest)
|
||||
|
||||
# The move could fail if the dest has xattr protections, so delete the
|
||||
# temp file in this case
|
||||
try:
|
||||
shutil.move(tgt, dest)
|
||||
except Exception:
|
||||
__clean_tmp(tgt)
|
||||
raise
|
||||
|
||||
if fstat is not None:
|
||||
os.chown(dest, fstat.st_uid, fstat.st_gid)
|
||||
os.chmod(dest, fstat.st_mode)
|
||||
@ -111,10 +129,7 @@ def copyfile(source, dest, backup_mode='', cachedir=''):
|
||||
subprocess.call(cmd, stdout=dev_null, stderr=dev_null)
|
||||
if os.path.isfile(tgt):
|
||||
# The temp file failed to move
|
||||
try:
|
||||
os.remove(tgt)
|
||||
except Exception:
|
||||
pass
|
||||
__clean_tmp(tgt)
|
||||
|
||||
|
||||
def rename(src, dst):
|
||||
|
@ -106,6 +106,62 @@ class OutputReturnTest(integration.ShellCase):
|
||||
trace = traceback.format_exc()
|
||||
self.assertEqual(trace, '')
|
||||
|
||||
def test_output_highstate(self):
|
||||
'''
|
||||
Regression tests for the highstate outputter. Calls a basic state with various
|
||||
flags. Each comparison should be identical when successful.
|
||||
'''
|
||||
# Test basic highstate output. No frills.
|
||||
expected = ['minion:', ' ID: simple-ping', ' Function: module.run',
|
||||
' Name: test.ping', ' Result: True',
|
||||
' Comment: Module function test.ping executed',
|
||||
' Changes: ', ' ret:', ' True',
|
||||
'Summary for minion', 'Succeeded: 1 (changed=1)', 'Failed: 0',
|
||||
'Total states run: 1']
|
||||
state_run = self.run_salt('"minion" state.sls simple-ping')
|
||||
|
||||
for expected_item in expected:
|
||||
self.assertIn(expected_item, state_run)
|
||||
|
||||
# Test highstate output while also passing --out=highstate.
|
||||
# This is a regression test for Issue #29796
|
||||
state_run = self.run_salt('"minion" state.sls simple-ping --out=highstate')
|
||||
|
||||
for expected_item in expected:
|
||||
self.assertIn(expected_item, state_run)
|
||||
|
||||
# Test highstate output when passing --static and running a state function.
|
||||
# See Issue #44556.
|
||||
state_run = self.run_salt('"minion" state.sls simple-ping --static')
|
||||
|
||||
for expected_item in expected:
|
||||
self.assertIn(expected_item, state_run)
|
||||
|
||||
# Test highstate output when passing --static and --out=highstate.
|
||||
# See Issue #44556.
|
||||
state_run = self.run_salt('"minion" state.sls simple-ping --static --out=highstate')
|
||||
|
||||
for expected_item in expected:
|
||||
self.assertIn(expected_item, state_run)
|
||||
|
||||
def test_output_highstate_falls_back_nested(self):
|
||||
'''
|
||||
Tests outputter when passing --out=highstate with a non-state call. This should
|
||||
fall back to "nested" output.
|
||||
'''
|
||||
expected = ['minion:', ' True']
|
||||
ret = self.run_salt('"minion" test.ping --out=highstate')
|
||||
self.assertEqual(ret, expected)
|
||||
|
||||
def test_static_simple(self):
|
||||
'''
|
||||
Tests passing the --static option with a basic test.ping command. This
|
||||
should be the "nested" output.
|
||||
'''
|
||||
expected = ['minion:', ' True']
|
||||
ret = self.run_salt('"minion" test.ping --static')
|
||||
self.assertEqual(ret, expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
@ -104,9 +104,9 @@ def _test_managed_file_mode_keep_helper(testcase, local=False):
|
||||
# Get the current mode so that we can put the file back the way we
|
||||
# found it when we're done.
|
||||
grail_fs_mode = os.stat(grail_fs_path).st_mode
|
||||
initial_mode = 504 # 0770 octal
|
||||
new_mode_1 = 384 # 0600 octal
|
||||
new_mode_2 = 420 # 0644 octal
|
||||
initial_mode = 0o770
|
||||
new_mode_1 = 0o600
|
||||
new_mode_2 = 0o644
|
||||
|
||||
# Set the initial mode, so we can be assured that when we set the mode
|
||||
# to "keep", we're actually changing the permissions of the file to the
|
||||
@ -587,6 +587,86 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
|
||||
for typ in managed_files:
|
||||
os.remove(managed_files[typ])
|
||||
|
||||
def test_managed_local_source_with_source_hash(self):
|
||||
'''
|
||||
Make sure that we enforce the source_hash even with local files
|
||||
'''
|
||||
name = os.path.join(integration.TMP, 'local_source_with_source_hash')
|
||||
local_path = os.path.join(
|
||||
integration.FILES, 'file', 'base', 'grail', 'scene33')
|
||||
actual_hash = '567fd840bf1548edc35c48eb66cdd78bfdfcccff'
|
||||
# Reverse the actual hash
|
||||
bad_hash = actual_hash[::-1]
|
||||
|
||||
def remove_file():
|
||||
try:
|
||||
os.remove(name)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
def do_test(clean=False):
|
||||
for proto in ('file://', ''):
|
||||
source = proto + local_path
|
||||
log.debug('Trying source %s', source)
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=source,
|
||||
source_hash='sha1={0}'.format(bad_hash))
|
||||
self.assertSaltFalseReturn(ret)
|
||||
ret = ret[next(iter(ret))]
|
||||
# Shouldn't be any changes
|
||||
self.assertFalse(ret['changes'])
|
||||
# Check that we identified a hash mismatch
|
||||
self.assertIn(
|
||||
'does not match actual checksum', ret['comment'])
|
||||
|
||||
ret = self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=source,
|
||||
source_hash='sha1={0}'.format(actual_hash))
|
||||
self.assertSaltTrueReturn(ret)
|
||||
finally:
|
||||
if clean:
|
||||
remove_file()
|
||||
|
||||
remove_file()
|
||||
log.debug('Trying with nonexistant destination file')
|
||||
do_test()
|
||||
log.debug('Trying with destination file already present')
|
||||
with salt.utils.fopen(name, 'w'):
|
||||
pass
|
||||
try:
|
||||
do_test(clean=False)
|
||||
finally:
|
||||
remove_file()
|
||||
|
||||
def test_managed_local_source_does_not_exist(self):
|
||||
'''
|
||||
Make sure that we exit gracefully when a local source doesn't exist
|
||||
'''
|
||||
name = os.path.join(integration.TMP, 'local_source_does_not_exist')
|
||||
local_path = os.path.join(
|
||||
integration.FILES, 'file', 'base', 'grail', 'scene99')
|
||||
|
||||
for proto in ('file://', ''):
|
||||
source = proto + local_path
|
||||
log.debug('Trying source %s', source)
|
||||
ret = self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=source)
|
||||
self.assertSaltFalseReturn(ret)
|
||||
ret = ret[next(iter(ret))]
|
||||
# Shouldn't be any changes
|
||||
self.assertFalse(ret['changes'])
|
||||
# Check that we identified a hash mismatch
|
||||
self.assertIn(
|
||||
'does not exist', ret['comment'])
|
||||
|
||||
def test_directory(self):
|
||||
'''
|
||||
file.directory
|
||||
|
@ -28,6 +28,15 @@ from salt.grains import core
|
||||
|
||||
# Globals
|
||||
core.__salt__ = {}
|
||||
core.__opts__ = {}
|
||||
IPv4Address = salt.ext.ipaddress.IPv4Address
|
||||
IPv6Address = salt.ext.ipaddress.IPv6Address
|
||||
IP4_LOCAL = '127.0.0.1'
|
||||
IP4_ADD1 = '10.0.0.1'
|
||||
IP4_ADD2 = '10.0.0.2'
|
||||
IP6_LOCAL = '::1'
|
||||
IP6_ADD1 = '2001:4860:4860::8844'
|
||||
IP6_ADD2 = '2001:4860:4860::8888'
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
@ -459,6 +468,130 @@ PATCHLEVEL = 3
|
||||
self.assertListEqual(list(os_grains.get('osrelease_info')), os_release_map['osrelease_info'])
|
||||
self.assertEqual(os_grains.get('osmajorrelease'), os_release_map['osmajorrelease'])
|
||||
|
||||
def _check_ipaddress(self, value, ip_v):
|
||||
'''
|
||||
check if ip address in a list is valid
|
||||
'''
|
||||
for val in value:
|
||||
assert isinstance(val, six.string_types)
|
||||
ip_method = 'is_ipv{0}'.format(ip_v)
|
||||
self.assertTrue(getattr(salt.utils.network, ip_method)(val))
|
||||
|
||||
def _check_empty(self, key, value, empty):
|
||||
'''
|
||||
if empty is False and value does not exist assert error
|
||||
if empty is True and value exists assert error
|
||||
'''
|
||||
if not empty and not value:
|
||||
raise Exception("{0} is empty, expecting a value".format(key))
|
||||
elif empty and value:
|
||||
raise Exception("{0} is suppose to be empty. value: {1} \
|
||||
exists".format(key, value))
|
||||
|
||||
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
|
||||
def test_fqdn_return(self):
|
||||
'''
|
||||
test ip4 and ip6 return values
|
||||
'''
|
||||
net_ip4_mock = [IP4_LOCAL, IP4_ADD1, IP4_ADD2]
|
||||
net_ip6_mock = [IP6_LOCAL, IP6_ADD1, IP6_ADD2]
|
||||
|
||||
self._run_fqdn_tests(net_ip4_mock, net_ip6_mock,
|
||||
ip4_empty=False, ip6_empty=False)
|
||||
|
||||
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
|
||||
def test_fqdn6_empty(self):
|
||||
'''
|
||||
test when ip6 is empty
|
||||
'''
|
||||
net_ip4_mock = [IP4_LOCAL, IP4_ADD1, IP4_ADD2]
|
||||
net_ip6_mock = []
|
||||
|
||||
self._run_fqdn_tests(net_ip4_mock, net_ip6_mock,
|
||||
ip4_empty=False)
|
||||
|
||||
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
|
||||
def test_fqdn4_empty(self):
|
||||
'''
|
||||
test when ip4 is empty
|
||||
'''
|
||||
net_ip4_mock = []
|
||||
net_ip6_mock = [IP6_LOCAL, IP6_ADD1, IP6_ADD2]
|
||||
|
||||
self._run_fqdn_tests(net_ip4_mock, net_ip6_mock,
|
||||
ip6_empty=False)
|
||||
|
||||
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
|
||||
def test_fqdn_all_empty(self):
|
||||
'''
|
||||
test when both ip4 and ip6 are empty
|
||||
'''
|
||||
net_ip4_mock = []
|
||||
net_ip6_mock = []
|
||||
|
||||
self._run_fqdn_tests(net_ip4_mock, net_ip6_mock)
|
||||
|
||||
def _run_fqdn_tests(self, net_ip4_mock, net_ip6_mock,
|
||||
ip6_empty=True, ip4_empty=True):
|
||||
|
||||
def _check_type(key, value, ip4_empty, ip6_empty):
|
||||
'''
|
||||
check type and other checks
|
||||
'''
|
||||
assert isinstance(value, list)
|
||||
|
||||
if '4' in key:
|
||||
self._check_empty(key, value, ip4_empty)
|
||||
self._check_ipaddress(value, ip_v='4')
|
||||
elif '6' in key:
|
||||
self._check_empty(key, value, ip6_empty)
|
||||
self._check_ipaddress(value, ip_v='6')
|
||||
|
||||
ip4_mock = [(2, 1, 6, '', (IP4_ADD1, 0)),
|
||||
(2, 3, 0, '', (IP4_ADD2, 0))]
|
||||
ip6_mock = [(10, 1, 6, '', (IP6_ADD1, 0, 0, 0)),
|
||||
(10, 3, 0, '', (IP6_ADD2, 0, 0, 0))]
|
||||
|
||||
with patch.dict(core.__opts__, {'ipv6': False}):
|
||||
with patch.object(salt.utils.network, 'ip_addrs',
|
||||
MagicMock(return_value=net_ip4_mock)):
|
||||
with patch.object(salt.utils.network, 'ip_addrs6',
|
||||
MagicMock(return_value=net_ip6_mock)):
|
||||
with patch.object(core.socket, 'getaddrinfo', side_effect=[ip4_mock, ip6_mock]):
|
||||
get_fqdn = core.ip_fqdn()
|
||||
ret_keys = ['fqdn_ip4', 'fqdn_ip6', 'ipv4', 'ipv6']
|
||||
for key in ret_keys:
|
||||
value = get_fqdn[key]
|
||||
_check_type(key, value, ip4_empty, ip6_empty)
|
||||
|
||||
@skipIf(not salt.utils.is_linux(), 'System is not Linux')
|
||||
def test_dns_return(self):
|
||||
'''
|
||||
test the return for a dns grain. test for issue:
|
||||
https://github.com/saltstack/salt/issues/41230
|
||||
'''
|
||||
resolv_mock = {'domain': '', 'sortlist': [], 'nameservers':
|
||||
[IPv4Address(IP4_ADD1),
|
||||
IPv6Address(IP6_ADD1)], 'ip4_nameservers':
|
||||
[IPv4Address(IP4_ADD1)],
|
||||
'search': ['test.saltstack.com'], 'ip6_nameservers':
|
||||
[IPv6Address(IP6_ADD1)], 'options': []}
|
||||
ret = {'dns': {'domain': '', 'sortlist': [], 'nameservers':
|
||||
[IP4_ADD1, IP6_ADD1], 'ip4_nameservers':
|
||||
[IP4_ADD1], 'search': ['test.saltstack.com'],
|
||||
'ip6_nameservers': [IP6_ADD1], 'options':
|
||||
[]}}
|
||||
self._run_dns_test(resolv_mock, ret)
|
||||
|
||||
def _run_dns_test(self, resolv_mock, ret):
|
||||
with patch.object(salt.utils, 'is_windows',
|
||||
MagicMock(return_value=False)):
|
||||
with patch.dict(core.__opts__, {'ipv6': False}):
|
||||
with patch.object(salt.utils.dns, 'parse_resolv',
|
||||
MagicMock(return_value=resolv_mock)):
|
||||
get_dns = core.dns()
|
||||
self.assertEqual(get_dns, ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
@ -581,7 +581,7 @@ class FileTestCase(TestCase):
|
||||
'file.copy': mock_cp,
|
||||
'file.manage_file': mock_ex,
|
||||
'cmd.run_all': mock_cmd_fail}):
|
||||
comt = ('Must provide name to file.exists')
|
||||
comt = ('Destination file name is required')
|
||||
ret.update({'comment': comt, 'name': '', 'pchanges': {}})
|
||||
self.assertDictEqual(filestate.managed(''), ret)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user