mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Python 3 Fixes (Pt. 2) (#39397)
* Typo in comment * First convert to string if not already a string. Then to bytes under Py3. The reason being that jids from the CLI, at least the one fed in integration.runners.jobs.ManageTest.test_loopup_jid is loaded as an integer, and, while the Py2 code converts JIDs to strings, under Py3, we assume JID's are already strings. * Mark tests which require root permissions to run * Allow declaring that the function IS a class method. ``` Python 3.5.3 (default, Jan 21 2017, 00:29:12) [GCC 6.3.1 20170109] on linux Type "help", "copyright", "credits" or "license" for more information. >>> class Foo: ... def bar(self): ... print('bar') ... >>> import inspect >>> inspect.ismethod(Foo.bar) False >>> inspect.ismethod(Foo().bar) True ``` On Python 2, `inspect.ismethod` returns `True` for bound and unbound methods while on Python 3 it only returns `True` for bound methods. The explicit `is_class_method` is to avoid instantiating the class just to get the function signature. * Always decode responses to the Python version native string implementation * Just compare the objects as matching list. Asserting same item count doesn't make that much sense. * Py3 compatibility * Fix saltnado tests under Py3 * Python 3 compatibility * Show me the full traceback * Revert "Convert fileserver data from bytes to strings" This reverts commite53972f8c6
. * Revert "Under Py3, we get `bytes` when using the roots backend directly" This reverts commit9f73b240c1
. * Convert from bytes to str if not a binary file * Py3 compatibility fixes. Convert file contents from bytes to string if not a binary file
This commit is contained in:
parent
b5d56890ce
commit
fc59d5e832
16 changed files with 135 additions and 119 deletions
|
@ -350,7 +350,7 @@ class SyncClientMixin(object):
|
|||
for global_key, value in six.iteritems(func_globals):
|
||||
self.functions[mod_name].__globals__[global_key] = value
|
||||
|
||||
# There are some descrepencies of what a "low" structure is in the
|
||||
# There are some discrepancies of what a "low" structure is in the
|
||||
# publisher world it is a dict including stuff such as jid, fun,
|
||||
# arg (a list of args, with kwargs packed in). Historically this
|
||||
# particular one has had no "arg" and just has had all the kwargs
|
||||
|
|
|
@ -594,9 +594,7 @@ class Fileserver(object):
|
|||
return ret
|
||||
fstr = '{0}.serve_file'.format(fnd['back'])
|
||||
if fstr in self.servers:
|
||||
ret = self.servers[fstr](load, fnd)
|
||||
if six.PY3 and ret.get('data'):
|
||||
ret['data'] = ret['data'].decode(__salt_system_encoding__)
|
||||
return self.servers[fstr](load, fnd)
|
||||
return ret
|
||||
|
||||
def __file_hash_and_stat(self, load):
|
||||
|
|
|
@ -129,9 +129,12 @@ def serve_file(load, fnd):
|
|||
return ret
|
||||
ret['dest'] = fnd['rel']
|
||||
gzip = load.get('gzip', None)
|
||||
with salt.utils.fopen(os.path.normpath(fnd['path']), 'rb') as fp_:
|
||||
fpath = os.path.normpath(fnd['path'])
|
||||
with salt.utils.fopen(fpath, 'rb') as fp_:
|
||||
fp_.seek(load['loc'])
|
||||
data = fp_.read(__opts__['file_buffer_size'])
|
||||
if data and six.PY3 and not salt.utils.is_bin_file(fpath):
|
||||
data = data.decode(__salt_system_encoding__)
|
||||
if gzip and data:
|
||||
data = salt.utils.gzip_util.compress(data, gzip)
|
||||
ret['gzip'] = gzip
|
||||
|
|
|
@ -199,6 +199,7 @@ from collections import defaultdict
|
|||
# pylint: disable=import-error
|
||||
import cgi
|
||||
import yaml
|
||||
import tornado.escape
|
||||
import tornado.httpserver
|
||||
import tornado.ioloop
|
||||
import tornado.web
|
||||
|
@ -523,7 +524,7 @@ class BaseSaltAPIHandler(tornado.web.RequestHandler, SaltClientsMixIn): # pylin
|
|||
# Use cgi.parse_header to correctly separate parameters from value
|
||||
header = cgi.parse_header(self.request.headers['Content-Type'])
|
||||
value, parameters = header
|
||||
return ct_in_map[value](data)
|
||||
return ct_in_map[value](tornado.escape.native_str(data))
|
||||
except KeyError:
|
||||
self.send_error(406)
|
||||
except ValueError:
|
||||
|
@ -1059,7 +1060,7 @@ class SaltAPIHandler(BaseSaltAPIHandler, SaltClientsMixIn): # pylint: disable=W
|
|||
|
||||
# salt.utils.format_call doesn't work for functions having the annotation tornado.gen.coroutine
|
||||
def _format_call_run_job_async(self, chunk):
|
||||
f_call = salt.utils.format_call(salt.client.LocalClient.run_job, chunk)
|
||||
f_call = salt.utils.format_call(salt.client.LocalClient.run_job, chunk, is_class_method=True)
|
||||
f_call.get('kwargs', {})['io_loop'] = tornado.ioloop.IOLoop.current()
|
||||
return f_call
|
||||
|
||||
|
|
|
@ -257,12 +257,14 @@ def _decrypt_ciphertext(cipher, translate_newlines=False):
|
|||
the cipher and return the decrypted string. If the cipher cannot be
|
||||
decrypted, log the error, and return the ciphertext back out.
|
||||
'''
|
||||
if translate_newlines:
|
||||
cipher = cipher.replace(r'\n', '\n')
|
||||
if six.PY3:
|
||||
cipher = cipher.encode(__salt_system_encoding__)
|
||||
cmd = [_get_gpg_exec(), '--homedir', _get_key_dir(), '--status-fd', '2',
|
||||
'--no-tty', '-d']
|
||||
proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
|
||||
decrypted_data, decrypt_error = proc.communicate(
|
||||
input=cipher.replace(r'\n', '\n') if translate_newlines else cipher
|
||||
)
|
||||
decrypted_data, decrypt_error = proc.communicate(input=cipher)
|
||||
if not decrypted_data:
|
||||
log.warning(
|
||||
'Could not decrypt cipher %s, received: %s',
|
||||
|
@ -271,6 +273,8 @@ def _decrypt_ciphertext(cipher, translate_newlines=False):
|
|||
)
|
||||
return cipher
|
||||
else:
|
||||
if six.PY3:
|
||||
decrypted_data = decrypted_data.decode(__salt_system_encoding__)
|
||||
return str(decrypted_data)
|
||||
|
||||
|
||||
|
|
|
@ -1016,7 +1016,8 @@ def build_whitespace_split_regex(text):
|
|||
def format_call(fun,
|
||||
data,
|
||||
initial_ret=None,
|
||||
expected_extra_kws=()):
|
||||
expected_extra_kws=(),
|
||||
is_class_method=None):
|
||||
'''
|
||||
Build the required arguments and keyword arguments required for the passed
|
||||
function.
|
||||
|
@ -1028,6 +1029,13 @@ def format_call(fun,
|
|||
None
|
||||
:param expected_extra_kws: Any expected extra keyword argument names which
|
||||
should not trigger a :ref:`SaltInvocationError`
|
||||
:param is_class_method: Pass True if you are sure that the function being passed
|
||||
is a class method. The reason for this is that on Python 3
|
||||
``inspect.ismethod`` only returns ``True`` for bound methods,
|
||||
while on Python 2, it returns ``True`` for bound and unbound
|
||||
methods. So, on Python 3, in case of a class method, you'd
|
||||
need the class to which the function belongs to be instantiated
|
||||
and this is not always wanted.
|
||||
:returns: A dictionary with the function required arguments and keyword
|
||||
arguments.
|
||||
'''
|
||||
|
@ -1036,7 +1044,7 @@ def format_call(fun,
|
|||
ret['args'] = []
|
||||
ret['kwargs'] = {}
|
||||
|
||||
aspec = salt.utils.args.get_function_argspec(fun)
|
||||
aspec = salt.utils.args.get_function_argspec(fun, is_class_method=is_class_method)
|
||||
|
||||
arg_data = arg_lookup(fun, aspec)
|
||||
args = arg_data['args']
|
||||
|
|
|
@ -170,15 +170,25 @@ if six.PY3:
|
|||
return _ArgSpec(args, varargs, varkw, defaults)
|
||||
|
||||
|
||||
def get_function_argspec(func):
|
||||
def get_function_argspec(func, is_class_method=None):
|
||||
'''
|
||||
A small wrapper around getargspec that also supports callable classes
|
||||
:param is_class_method: Pass True if you are sure that the function being passed
|
||||
is a class method. The reason for this is that on Python 3
|
||||
``inspect.ismethod`` only returns ``True`` for bound methods,
|
||||
while on Python 2, it returns ``True`` for bound and unbound
|
||||
methods. So, on Python 3, in case of a class method, you'd
|
||||
need the class to which the function belongs to be instantiated
|
||||
and this is not always wanted.
|
||||
'''
|
||||
if not callable(func):
|
||||
raise TypeError('{0} is not a callable'.format(func))
|
||||
|
||||
if six.PY2:
|
||||
if inspect.isfunction(func):
|
||||
if is_class_method is True:
|
||||
aspec = inspect.getargspec(func)
|
||||
del aspec.args[0] # self
|
||||
elif inspect.isfunction(func):
|
||||
aspec = inspect.getargspec(func)
|
||||
elif inspect.ismethod(func):
|
||||
aspec = inspect.getargspec(func)
|
||||
|
@ -191,7 +201,10 @@ def get_function_argspec(func):
|
|||
'Cannot inspect argument list for \'{0}\''.format(func)
|
||||
)
|
||||
else:
|
||||
if inspect.isfunction(func):
|
||||
if is_class_method is True:
|
||||
aspec = _getargspec(func)
|
||||
del aspec.args[0] # self
|
||||
elif inspect.isfunction(func):
|
||||
aspec = _getargspec(func) # pylint: disable=redefined-variable-type
|
||||
elif inspect.ismethod(func):
|
||||
aspec = _getargspec(func)
|
||||
|
|
|
@ -454,6 +454,8 @@ class GitProvider(object):
|
|||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
output = cmd.communicate()[0]
|
||||
if six.PY3:
|
||||
output = output.decode(__salt_system_encoding__)
|
||||
if cmd.returncode != 0:
|
||||
log.warning(
|
||||
'Failed to prune stale branches for %s remote \'%s\'. '
|
||||
|
@ -601,7 +603,7 @@ class GitProvider(object):
|
|||
os.O_CREAT | os.O_EXCL | os.O_WRONLY)
|
||||
with os.fdopen(fh_, 'w'):
|
||||
# Write the lock file and close the filehandle
|
||||
os.write(fh_, str(os.getpid()))
|
||||
os.write(fh_, six.b(str(os.getpid())))
|
||||
except (OSError, IOError) as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
with salt.utils.fopen(self._get_lock_file(lock_type), 'r') as fd_:
|
||||
|
@ -2078,7 +2080,8 @@ class GitBase(object):
|
|||
os.makedirs(env_cachedir)
|
||||
new_envs = self.envs(ignore_cache=True)
|
||||
serial = salt.payload.Serial(self.opts)
|
||||
with salt.utils.fopen(self.env_cache, 'w+') as fp_:
|
||||
mode = 'wb+' if six.PY3 else 'w+'
|
||||
with salt.utils.fopen(self.env_cache, mode) as fp_:
|
||||
fp_.write(serial.dumps(new_envs))
|
||||
log.trace('Wrote env cache data to {0}'.format(self.env_cache))
|
||||
|
||||
|
@ -2480,9 +2483,12 @@ class GitFS(GitBase):
|
|||
return ret
|
||||
ret['dest'] = fnd['rel']
|
||||
gzip = load.get('gzip', None)
|
||||
with salt.utils.fopen(fnd['path'], 'rb') as fp_:
|
||||
fpath = os.path.normpath(fnd['path'])
|
||||
with salt.utils.fopen(fpath, 'rb') as fp_:
|
||||
fp_.seek(load['loc'])
|
||||
data = fp_.read(self.opts['file_buffer_size'])
|
||||
if data and six.PY3 and not salt.utils.is_bin_file(fpath):
|
||||
data = data.decode(__salt_system_encoding__)
|
||||
if gzip and data:
|
||||
data = salt.utils.gzip_util.compress(data, gzip)
|
||||
ret['gzip'] = gzip
|
||||
|
|
|
@ -101,10 +101,11 @@ def jid_dir(jid, job_dir=None, hash_type='sha256'):
|
|||
'''
|
||||
Return the jid_dir for the given job id
|
||||
'''
|
||||
if not isinstance(jid, six.string_types):
|
||||
jid = str(jid)
|
||||
if six.PY3:
|
||||
jhash = getattr(hashlib, hash_type)(jid.encode('utf-8')).hexdigest()
|
||||
else:
|
||||
jhash = getattr(hashlib, hash_type)(str(jid)).hexdigest()
|
||||
jid = jid.encode('utf-8')
|
||||
jhash = getattr(hashlib, hash_type)(jid).hexdigest()
|
||||
|
||||
parts = []
|
||||
if job_dir is not None:
|
||||
|
|
|
@ -139,7 +139,10 @@ class VirtualboxProviderTest(VirtualboxCloudTestCase):
|
|||
names = machines.keys()
|
||||
self.assertGreaterEqual(len(names), 1, "No machines found")
|
||||
for name, machine in six.iteritems(machines):
|
||||
self.assertItemsEqual(expected_attributes, machine.keys())
|
||||
if six.PY3:
|
||||
self.assertCountEqual(expected_attributes, machine.keys())
|
||||
else:
|
||||
self.assertItemsEqual(expected_attributes, machine.keys())
|
||||
|
||||
self.assertIn(BASE_BOX_NAME, names)
|
||||
|
||||
|
@ -168,7 +171,10 @@ class VirtualboxProviderTest(VirtualboxCloudTestCase):
|
|||
names = machines.keys()
|
||||
self.assertGreaterEqual(len(names), 1, "No machines found")
|
||||
for name, machine in six.iteritems(machines):
|
||||
self.assertItemsEqual(expected_attributes, machine.keys())
|
||||
if six.PY3:
|
||||
self.assertCountEqual(expected_attributes, machine.keys())
|
||||
else:
|
||||
self.assertItemsEqual(expected_attributes, machine.keys())
|
||||
|
||||
self.assertIn(BASE_BOX_NAME, names)
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ import integration
|
|||
from salt.fileserver import roots
|
||||
from salt import fileclient
|
||||
|
||||
# Import third party libs
|
||||
import salt.ext.six as six
|
||||
|
||||
roots.__opts__ = {}
|
||||
|
||||
|
||||
|
@ -71,19 +68,19 @@ class RootsTest(integration.ModuleCase):
|
|||
ret = roots.serve_file(load, fnd)
|
||||
self.assertDictEqual(
|
||||
ret,
|
||||
{'data': six.b('Scene 24\n\n \n OLD MAN: Ah, hee he he ha!\n '
|
||||
'ARTHUR: And this enchanter of whom you speak, he '
|
||||
'has seen the grail?\n OLD MAN: Ha ha he he he '
|
||||
'he!\n ARTHUR: Where does he live? Old man, where '
|
||||
'does he live?\n OLD MAN: He knows of a cave, a '
|
||||
'cave which no man has entered.\n ARTHUR: And the '
|
||||
'Grail... The Grail is there?\n OLD MAN: Very much '
|
||||
'danger, for beyond the cave lies the Gorge\n '
|
||||
'of Eternal Peril, which no man has ever crossed.\n '
|
||||
'ARTHUR: But the Grail! Where is the Grail!?\n '
|
||||
'OLD MAN: Seek you the Bridge of Death.\n ARTHUR: '
|
||||
'The Bridge of Death, which leads to the Grail?\n '
|
||||
'OLD MAN: Hee hee ha ha!\n\n'),
|
||||
{'data': 'Scene 24\n\n \n OLD MAN: Ah, hee he he ha!\n '
|
||||
'ARTHUR: And this enchanter of whom you speak, he '
|
||||
'has seen the grail?\n OLD MAN: Ha ha he he he '
|
||||
'he!\n ARTHUR: Where does he live? Old man, where '
|
||||
'does he live?\n OLD MAN: He knows of a cave, a '
|
||||
'cave which no man has entered.\n ARTHUR: And the '
|
||||
'Grail... The Grail is there?\n OLD MAN: Very much '
|
||||
'danger, for beyond the cave lies the Gorge\n '
|
||||
'of Eternal Peril, which no man has ever crossed.\n '
|
||||
'ARTHUR: But the Grail! Where is the Grail!?\n '
|
||||
'OLD MAN: Seek you the Bridge of Death.\n ARTHUR: '
|
||||
'The Bridge of Death, which leads to the Grail?\n '
|
||||
'OLD MAN: Hee hee ha ha!\n\n',
|
||||
'dest': 'testfile'})
|
||||
|
||||
@skipIf(True, "Update test not yet implemented")
|
||||
|
|
|
@ -23,12 +23,15 @@ from subprocess import Popen, PIPE, STDOUT
|
|||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
ensure_in_syspath('..')
|
||||
import salt.ext.six as six
|
||||
|
||||
# Import salt libs
|
||||
import integration
|
||||
import salt.utils
|
||||
from salt import pillar
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
ensure_in_syspath('..')
|
||||
|
||||
|
||||
GPG_HOMEDIR = os.path.join(integration.TMP_CONF_DIR, 'gpgkeys')
|
||||
|
@ -224,7 +227,7 @@ class DecryptGPGPillarTest(integration.ModuleCase):
|
|||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
stderr=STDOUT,
|
||||
shell=False).communicate(input=TEST_KEY)[0]
|
||||
shell=False).communicate(input=six.b(TEST_KEY))[0]
|
||||
log.debug('Result:\n%s', output)
|
||||
|
||||
os.makedirs(PILLAR_BASE)
|
||||
|
|
|
@ -17,7 +17,6 @@ from salttesting.mock import patch, MagicMock
|
|||
ensure_in_syspath('../../')
|
||||
|
||||
# Import salt libs
|
||||
import salt.ext.six as six
|
||||
import integration
|
||||
import salt.utils
|
||||
from salt.modules import file as filemod
|
||||
|
@ -167,10 +166,7 @@ class FileModuleTest(integration.ModuleCase):
|
|||
def test_source_list_for_single_file_returns_unchanged(self):
|
||||
ret = self.run_function('file.source_list', ['salt://http/httpd.conf',
|
||||
'filehash', 'base'])
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['salt://http/httpd.conf', 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['salt://http/httpd.conf', 'filehash'])
|
||||
self.assertEqual(list(ret), ['salt://http/httpd.conf', 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_existing_file(self):
|
||||
filemod.__salt__ = {
|
||||
|
@ -183,12 +179,7 @@ class FileModuleTest(integration.ModuleCase):
|
|||
ret = filemod.source_list(['salt://http/httpd.conf',
|
||||
'salt://http/httpd.conf.fallback'],
|
||||
'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['salt://http/httpd.conf.fallback',
|
||||
'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['salt://http/httpd.conf.fallback',
|
||||
'filehash'])
|
||||
self.assertEqual(list(ret), ['salt://http/httpd.conf.fallback', 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_file_from_other_env(self):
|
||||
def list_master(env):
|
||||
|
@ -203,12 +194,7 @@ class FileModuleTest(integration.ModuleCase):
|
|||
ret = filemod.source_list(['salt://http/httpd.conf?saltenv=dev',
|
||||
'salt://http/httpd.conf.fallback'],
|
||||
'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['salt://http/httpd.conf?saltenv=dev',
|
||||
'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['salt://http/httpd.conf?saltenv=dev',
|
||||
'filehash'])
|
||||
self.assertEqual(list(ret), ['salt://http/httpd.conf?saltenv=dev', 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_file_from_dict(self):
|
||||
filemod.__salt__ = {
|
||||
|
@ -219,10 +205,7 @@ class FileModuleTest(integration.ModuleCase):
|
|||
|
||||
ret = filemod.source_list(
|
||||
[{'salt://http/httpd.conf': ''}], 'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['salt://http/httpd.conf', 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['salt://http/httpd.conf', 'filehash'])
|
||||
self.assertEqual(list(ret), ['salt://http/httpd.conf', 'filehash'])
|
||||
|
||||
@patch('salt.modules.file.os.remove')
|
||||
def test_source_list_for_list_returns_file_from_dict_via_http(self, remove):
|
||||
|
@ -236,62 +219,39 @@ class FileModuleTest(integration.ModuleCase):
|
|||
|
||||
ret = filemod.source_list(
|
||||
[{'http://t.est.com/http/httpd.conf': 'filehash'}], '', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['http://t.est.com/http/httpd.conf',
|
||||
'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['http://t.est.com/http/httpd.conf',
|
||||
'filehash'])
|
||||
self.assertEqual(list(ret), ['http://t.est.com/http/httpd.conf', 'filehash'])
|
||||
|
||||
def test_source_list_for_single_local_file_slash_returns_unchanged(self):
|
||||
ret = self.run_function('file.source_list', [self.myfile,
|
||||
'filehash', 'base'])
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, [self.myfile, 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, [self.myfile, 'filehash'])
|
||||
self.assertEqual(list(ret), [self.myfile, 'filehash'])
|
||||
|
||||
def test_source_list_for_single_local_file_proto_returns_unchanged(self):
|
||||
ret = self.run_function('file.source_list', ['file://' + self.myfile,
|
||||
'filehash', 'base'])
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['file://' + self.myfile, 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['file://' + self.myfile, 'filehash'])
|
||||
self.assertEqual(list(ret), ['file://' + self.myfile, 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_existing_local_file_slash(self):
|
||||
ret = filemod.source_list([self.myfile + '-foo',
|
||||
self.myfile],
|
||||
'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, [self.myfile, 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, [self.myfile, 'filehash'])
|
||||
self.assertEqual(list(ret), [self.myfile, 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_existing_local_file_proto(self):
|
||||
ret = filemod.source_list(['file://' + self.myfile + '-foo',
|
||||
'file://' + self.myfile],
|
||||
'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['file://' + self.myfile, 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['file://' + self.myfile, 'filehash'])
|
||||
self.assertEqual(list(ret), ['file://' + self.myfile, 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_local_file_slash_from_dict(self):
|
||||
ret = filemod.source_list(
|
||||
[{self.myfile: ''}], 'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, [self.myfile, 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, [self.myfile, 'filehash'])
|
||||
self.assertEqual(list(ret), [self.myfile, 'filehash'])
|
||||
|
||||
def test_source_list_for_list_returns_local_file_proto_from_dict(self):
|
||||
ret = filemod.source_list(
|
||||
[{'file://' + self.myfile: ''}], 'filehash', 'base')
|
||||
if six.PY3:
|
||||
self.assertCountEqual(ret, ['file://' + self.myfile, 'filehash'])
|
||||
else:
|
||||
self.assertItemsEqual(ret, ['file://' + self.myfile, 'filehash'])
|
||||
self.assertEqual(list(ret), ['file://' + self.myfile, 'filehash'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
|
|
@ -27,6 +27,12 @@ except ImportError:
|
|||
HAS_ZMQ_IOLOOP = False
|
||||
|
||||
|
||||
def json_loads(data):
|
||||
if six.PY3:
|
||||
data = data.decode('utf-8')
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
@skipIf(HAS_ZMQ_IOLOOP is False, 'PyZMQ version must be >= 14.0.1 to run these tests.')
|
||||
@skipIf(StrictVersion(zmq.__version__) < StrictVersion('14.0.1'), 'PyZMQ must be >= 14.0.1 to run these tests.')
|
||||
class TestSaltAPIHandler(SaltnadoTestCase):
|
||||
|
@ -47,13 +53,9 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
request_timeout=30,
|
||||
)
|
||||
self.assertEqual(response.code, 200)
|
||||
response_obj = json.loads(response.body)
|
||||
self.assertItemsEqual(response_obj['clients'],
|
||||
['runner',
|
||||
'runner_async',
|
||||
'local_async',
|
||||
'local']
|
||||
)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(sorted(response_obj['clients']),
|
||||
['local', 'local_async', 'runner', 'runner_async'])
|
||||
self.assertEqual(response_obj['return'], 'Welcome')
|
||||
|
||||
def test_post_no_auth(self):
|
||||
|
@ -94,7 +96,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
connect_timeout=30,
|
||||
request_timeout=30,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(response_obj['return'], [{'minion': True, 'sub_minion': True}])
|
||||
|
||||
def test_simple_local_post_no_tgt(self):
|
||||
|
@ -113,7 +115,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
connect_timeout=30,
|
||||
request_timeout=30,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(response_obj['return'], ["No minions matched the target. No command was sent, no jid was assigned."])
|
||||
|
||||
# local client request body test
|
||||
|
@ -133,7 +135,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
connect_timeout=30,
|
||||
request_timeout=30,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(response_obj['return'], [{'minion': True, 'sub_minion': True}])
|
||||
|
||||
def test_simple_local_post_invalid_request(self):
|
||||
|
@ -164,7 +166,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
ret = response_obj['return']
|
||||
ret[0]['minions'] = sorted(ret[0]['minions'])
|
||||
|
||||
|
@ -189,7 +191,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
ret = response_obj['return']
|
||||
ret[0]['minions'] = sorted(ret[0]['minions'])
|
||||
ret[1]['minions'] = sorted(ret[1]['minions'])
|
||||
|
@ -223,7 +225,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
ret = response_obj['return']
|
||||
ret[0]['minions'] = sorted(ret[0]['minions'])
|
||||
ret[1]['minions'] = sorted(ret[1]['minions'])
|
||||
|
@ -246,7 +248,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
headers={'Content-Type': self.content_type_map['json'],
|
||||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(response_obj['return'], [{}])
|
||||
|
||||
# runner tests
|
||||
|
@ -262,7 +264,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
connect_timeout=30,
|
||||
request_timeout=30,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(len(response_obj['return']), 1)
|
||||
self.assertEqual(set(response_obj['return'][0]), set(['minion', 'sub_minion']))
|
||||
|
||||
|
@ -279,7 +281,7 @@ class TestSaltAPIHandler(SaltnadoTestCase):
|
|||
connect_timeout=10,
|
||||
request_timeout=10,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertIn('return', response_obj)
|
||||
self.assertEqual(1, len(response_obj['return']))
|
||||
self.assertIn('jid', response_obj['return'][0])
|
||||
|
@ -303,7 +305,7 @@ class TestMinionSaltAPIHandler(SaltnadoTestCase):
|
|||
headers={saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
follow_redirects=False,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(len(response_obj['return']), 1)
|
||||
# one per minion
|
||||
self.assertEqual(len(response_obj['return'][0]), 2)
|
||||
|
@ -318,7 +320,7 @@ class TestMinionSaltAPIHandler(SaltnadoTestCase):
|
|||
headers={saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
follow_redirects=False,
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(len(response_obj['return']), 1)
|
||||
self.assertEqual(len(response_obj['return'][0]), 1)
|
||||
# check a single grain
|
||||
|
@ -335,7 +337,7 @@ class TestMinionSaltAPIHandler(SaltnadoTestCase):
|
|||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
ret = response_obj['return']
|
||||
ret[0]['minions'] = sorted(ret[0]['minions'])
|
||||
|
||||
|
@ -357,7 +359,7 @@ class TestMinionSaltAPIHandler(SaltnadoTestCase):
|
|||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
ret = response_obj['return']
|
||||
ret[0]['minions'] = sorted(ret[0]['minions'])
|
||||
|
||||
|
@ -405,7 +407,7 @@ class TestJobsSaltAPIHandler(SaltnadoTestCase):
|
|||
follow_redirects=False,
|
||||
)
|
||||
response = self.wait(timeout=30)
|
||||
response_obj = json.loads(response.body)['return'][0]
|
||||
response_obj = json_loads(response.body)['return'][0]
|
||||
try:
|
||||
for jid, ret in six.iteritems(response_obj):
|
||||
self.assertIn('Function', ret)
|
||||
|
@ -415,7 +417,7 @@ class TestJobsSaltAPIHandler(SaltnadoTestCase):
|
|||
self.assertIn('StartTime', ret)
|
||||
self.assertIn('Arguments', ret)
|
||||
except AttributeError as attribute_error:
|
||||
print(json.loads(response.body))
|
||||
print(json_loads(response.body))
|
||||
raise
|
||||
|
||||
# test with a specific JID passed in
|
||||
|
@ -427,7 +429,7 @@ class TestJobsSaltAPIHandler(SaltnadoTestCase):
|
|||
follow_redirects=False,
|
||||
)
|
||||
response = self.wait(timeout=30)
|
||||
response_obj = json.loads(response.body)['return'][0]
|
||||
response_obj = json_loads(response.body)['return'][0]
|
||||
self.assertIn('Function', response_obj)
|
||||
self.assertIn('Target', response_obj)
|
||||
self.assertIn('Target-type', response_obj)
|
||||
|
@ -460,7 +462,7 @@ class TestRunSaltAPIHandler(SaltnadoTestCase):
|
|||
headers={'Content-Type': self.content_type_map['json'],
|
||||
saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertEqual(response_obj['return'], [{'minion': True, 'sub_minion': True}])
|
||||
|
||||
|
||||
|
@ -488,6 +490,8 @@ class TestEventsSaltAPIHandler(SaltnadoTestCase):
|
|||
self.stop()
|
||||
|
||||
def on_event(self, event):
|
||||
if six.PY3:
|
||||
event = event.decode('utf-8')
|
||||
if self.events_to_fire > 0:
|
||||
self.application.event_listener.event.fire_event({
|
||||
'foo': 'bar',
|
||||
|
@ -544,7 +548,7 @@ class TestWebhookSaltAPIHandler(SaltnadoTestCase):
|
|||
body='foo=bar',
|
||||
headers={saltnado.AUTH_TOKEN_HEADER: self.token['token']},
|
||||
)
|
||||
response_obj = json.loads(response.body)
|
||||
response_obj = json_loads(response.body)
|
||||
self.assertTrue(response_obj['success'])
|
||||
|
||||
|
||||
|
|
|
@ -105,7 +105,16 @@ class OutputReturnTest(integration.ShellCase):
|
|||
except Exception:
|
||||
# display trace in error message for debugging on jenkins
|
||||
trace = traceback.format_exc()
|
||||
self.assertEqual(trace, '')
|
||||
sentinel = object()
|
||||
old_max_diff = getattr(self, 'maxDiff', sentinel)
|
||||
try:
|
||||
self.maxDiff = None
|
||||
self.assertEqual(trace, '')
|
||||
finally:
|
||||
if old_max_diff is sentinel:
|
||||
delattr(self, 'maxDiff')
|
||||
else:
|
||||
self.maxDiff = old_max_diff
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -11,6 +11,7 @@ import yaml
|
|||
import shutil
|
||||
|
||||
# Import Salt Testing libs
|
||||
from salttesting import skipIf
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
|
@ -175,6 +176,7 @@ class RunTest(integration.ShellCase, testprogram.TestProgramCase, integration.Sh
|
|||
stdout=stdout, stderr=stderr
|
||||
)
|
||||
|
||||
@skipIf(os.geteuid() != 0, 'You must be logged in as root to run this test')
|
||||
def test_salt_run_with_eauth_all_args(self):
|
||||
'''
|
||||
test salt-run with eauth
|
||||
|
@ -189,6 +191,7 @@ class RunTest(integration.ShellCase, testprogram.TestProgramCase, integration.Sh
|
|||
self.assertEqual(expect, run_cmd)
|
||||
self._remove_user()
|
||||
|
||||
@skipIf(os.geteuid() != 0, 'You must be logged in as root to run this test')
|
||||
def test_salt_run_with_eauth_bad_passwd(self):
|
||||
'''
|
||||
test salt-run with eauth and bad password
|
||||
|
|
Loading…
Add table
Reference in a new issue