mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2019.2' into 51821_ensure_result_comment_changes_valid_arguments
This commit is contained in:
commit
86c63b5723
18 changed files with 246 additions and 129 deletions
|
@ -289,7 +289,7 @@ a BGP policy referenced in many places, you can do so by running:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' net.replae_pattern OLD-POLICY-CONFIG new-policy-config
|
||||
salt '*' net.replace_pattern OLD-POLICY-CONFIG new-policy-config
|
||||
|
||||
Similarly, you can also replace entire configuration blocks using the
|
||||
:mod:`net.blockreplace <salt.modules.napalm_network.blockreplace>` function.
|
||||
|
|
|
@ -20,7 +20,6 @@ from salt.exceptions import (
|
|||
CommandExecutionError, MinionError
|
||||
)
|
||||
import salt.client
|
||||
import salt.crypt
|
||||
import salt.loader
|
||||
import salt.payload
|
||||
import salt.transport.client
|
||||
|
|
|
@ -2141,6 +2141,12 @@ def locale_info():
|
|||
def hostname():
|
||||
'''
|
||||
Return fqdn, hostname, domainname
|
||||
|
||||
.. note::
|
||||
On Windows the ``domain`` grain may refer to the dns entry for the host
|
||||
instead of the Windows domain to which the host is joined. It may also
|
||||
be empty if not a part of any domain. Refer to the ``windowsdomain``
|
||||
grain instead
|
||||
'''
|
||||
# This is going to need some work
|
||||
# Provides:
|
||||
|
|
|
@ -63,10 +63,12 @@ def _ctl_cmd(cmd, name, conf_file, bin_env):
|
|||
|
||||
|
||||
def _get_return(ret):
|
||||
if ret['retcode'] == 0:
|
||||
return ret['stdout']
|
||||
else:
|
||||
return ''
|
||||
retmsg = ret['stdout']
|
||||
if ret['retcode'] != 0:
|
||||
# This is a non 0 exit code
|
||||
if 'ERROR' not in retmsg:
|
||||
retmsg = 'ERROR: {}'.format(retmsg)
|
||||
return retmsg
|
||||
|
||||
|
||||
def start(name='all', user=None, conf_file=None, bin_env=None):
|
||||
|
|
|
@ -26,6 +26,7 @@ import sys
|
|||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import salt.utils.stringutils
|
||||
import salt.utils.data
|
||||
import salt.utils.platform
|
||||
import salt.exceptions
|
||||
from salt.ext import six
|
||||
|
@ -366,7 +367,6 @@ def _get_certificate_obj(cert):
|
|||
'''
|
||||
if isinstance(cert, M2Crypto.X509.X509):
|
||||
return cert
|
||||
|
||||
text = _text_or_file(cert)
|
||||
text = get_pem_entry(text, pem_type='CERTIFICATE')
|
||||
return M2Crypto.X509.load_cert_string(text)
|
||||
|
@ -1391,11 +1391,10 @@ def create_certificate(
|
|||
for ignore in list(_STATE_INTERNAL_KEYWORDS) + \
|
||||
['listen_in', 'preqrequired', '__prerequired__']:
|
||||
kwargs.pop(ignore, None)
|
||||
|
||||
certs = __salt__['publish.publish'](
|
||||
tgt=ca_server,
|
||||
fun='x509.sign_remote_certificate',
|
||||
arg=six.text_type(kwargs))
|
||||
arg=salt.utils.data.decode_dict(kwargs, to_str=True))
|
||||
|
||||
if not any(certs):
|
||||
raise salt.exceptions.SaltInvocationError(
|
||||
|
|
|
@ -19,7 +19,6 @@ import inspect
|
|||
import salt.loader
|
||||
import salt.fileclient
|
||||
import salt.minion
|
||||
import salt.crypt
|
||||
import salt.transport.client
|
||||
import salt.utils.args
|
||||
import salt.utils.cache
|
||||
|
|
|
@ -2736,7 +2736,7 @@ def managed(name,
|
|||
try:
|
||||
if __opts__['test']:
|
||||
if 'file.check_managed_changes' in __salt__:
|
||||
ret['pchanges'] = __salt__['file.check_managed_changes'](
|
||||
ret['changes'] = __salt__['file.check_managed_changes'](
|
||||
name,
|
||||
source,
|
||||
source_hash,
|
||||
|
@ -2767,15 +2767,17 @@ def managed(name,
|
|||
reset=win_perms_reset)
|
||||
except CommandExecutionError as exc:
|
||||
if exc.strerror.startswith('Path not found'):
|
||||
ret['pchanges'] = '{0} will be created'.format(name)
|
||||
ret['changes'] = {name: 'will be created'}
|
||||
|
||||
if isinstance(ret['pchanges'], tuple):
|
||||
ret['result'], ret['comment'] = ret['pchanges']
|
||||
elif ret['pchanges']:
|
||||
if isinstance(ret['changes'], tuple):
|
||||
ret['result'], ret['comment'] = ret['changes']
|
||||
elif ret['changes']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'The file {0} is set to be changed'.format(name)
|
||||
if 'diff' in ret['pchanges'] and not show_changes:
|
||||
ret['pchanges']['diff'] = '<show_changes=False>'
|
||||
ret['comment'] += ('\nNote: No changes made, actual changes may\n'
|
||||
'be different due to other states.')
|
||||
if 'diff' in ret['changes'] and not show_changes:
|
||||
ret['changes']['diff'] = '<show_changes=False>'
|
||||
else:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'The file {0} is in the correct state'.format(name)
|
||||
|
|
|
@ -10,7 +10,7 @@ import logging
|
|||
import socket
|
||||
import weakref
|
||||
import time
|
||||
import threading
|
||||
import sys
|
||||
|
||||
# Import 3rd-party libs
|
||||
import msgpack
|
||||
|
@ -85,6 +85,11 @@ class FutureWithTimeout(tornado.concurrent.Future):
|
|||
self.set_exception(exc)
|
||||
|
||||
|
||||
class IPCExceptionProxy(object):
|
||||
def __init__(self, orig_info):
|
||||
self.orig_info = orig_info
|
||||
|
||||
|
||||
class IPCServer(object):
|
||||
'''
|
||||
A Tornado IPC server very similar to Tornado's TCPServer class
|
||||
|
@ -244,36 +249,7 @@ class IPCClient(object):
|
|||
case it is used as the port for a tcp
|
||||
localhost connection.
|
||||
'''
|
||||
|
||||
# Create singleton map between two sockets
|
||||
instance_map = weakref.WeakKeyDictionary()
|
||||
|
||||
def __new__(cls, socket_path, io_loop=None):
|
||||
io_loop = io_loop or tornado.ioloop.IOLoop.current()
|
||||
if io_loop not in IPCClient.instance_map:
|
||||
IPCClient.instance_map[io_loop] = weakref.WeakValueDictionary()
|
||||
loop_instance_map = IPCClient.instance_map[io_loop]
|
||||
|
||||
# FIXME
|
||||
key = six.text_type(socket_path)
|
||||
|
||||
client = loop_instance_map.get(key)
|
||||
if client is None:
|
||||
log.debug('Initializing new IPCClient for path: %s', key)
|
||||
client = object.__new__(cls)
|
||||
# FIXME
|
||||
client.__singleton_init__(io_loop=io_loop, socket_path=socket_path)
|
||||
client._instance_key = key
|
||||
loop_instance_map[key] = client
|
||||
client._refcount = 1
|
||||
client._refcount_lock = threading.RLock()
|
||||
else:
|
||||
log.debug('Re-using IPCClient for %s', key)
|
||||
with client._refcount_lock:
|
||||
client._refcount += 1
|
||||
return client
|
||||
|
||||
def __singleton_init__(self, socket_path, io_loop=None):
|
||||
def __init__(self, socket_path, io_loop=None):
|
||||
'''
|
||||
Create a new IPC client
|
||||
|
||||
|
@ -292,10 +268,6 @@ class IPCClient(object):
|
|||
encoding = 'utf-8'
|
||||
self.unpacker = msgpack.Unpacker(encoding=encoding)
|
||||
|
||||
def __init__(self, socket_path, io_loop=None):
|
||||
# Handled by singleton __new__
|
||||
pass
|
||||
|
||||
def connected(self):
|
||||
return self.stream is not None and not self.stream.closed()
|
||||
|
||||
|
@ -367,16 +339,11 @@ class IPCClient(object):
|
|||
|
||||
def __del__(self):
|
||||
try:
|
||||
with self._refcount_lock:
|
||||
# Make sure we actually close no matter if something
|
||||
# went wrong with our ref counting
|
||||
self._refcount = 1
|
||||
try:
|
||||
self.close()
|
||||
except socket.error as exc:
|
||||
if exc.errno != errno.EBADF:
|
||||
# If its not a bad file descriptor error, raise
|
||||
raise
|
||||
self.close()
|
||||
except socket.error as exc:
|
||||
if exc.errno != errno.EBADF:
|
||||
# If its not a bad file descriptor error, raise
|
||||
raise
|
||||
except TypeError:
|
||||
# This is raised when Python's GC has collected objects which
|
||||
# would be needed when calling self.close()
|
||||
|
@ -391,16 +358,6 @@ class IPCClient(object):
|
|||
if self._closing:
|
||||
return
|
||||
|
||||
if self._refcount > 1:
|
||||
# Decrease refcount
|
||||
with self._refcount_lock:
|
||||
self._refcount -= 1
|
||||
log.debug(
|
||||
'This is not the last %s instance. Not closing yet.',
|
||||
self.__class__.__name__
|
||||
)
|
||||
return
|
||||
|
||||
self._closing = True
|
||||
|
||||
log.debug('Closing %s instance', self.__class__.__name__)
|
||||
|
@ -408,17 +365,6 @@ class IPCClient(object):
|
|||
if self.stream is not None and not self.stream.closed():
|
||||
self.stream.close()
|
||||
|
||||
# Remove the entry from the instance map so
|
||||
# that a closed entry may not be reused.
|
||||
# This forces this operation even if the reference
|
||||
# count of the entry has not yet gone to zero.
|
||||
if self.io_loop in self.__class__.instance_map:
|
||||
loop_instance_map = self.__class__.instance_map[self.io_loop]
|
||||
if self._instance_key in loop_instance_map:
|
||||
del loop_instance_map[self._instance_key]
|
||||
if not loop_instance_map:
|
||||
del self.__class__.instance_map[self.io_loop]
|
||||
|
||||
|
||||
class IPCMessageClient(IPCClient):
|
||||
'''
|
||||
|
@ -637,12 +583,13 @@ class IPCMessageSubscriberService(IPCClient):
|
|||
|
||||
To use this refer to IPCMessageSubscriber documentation.
|
||||
'''
|
||||
def __singleton_init__(self, socket_path, io_loop=None):
|
||||
super(IPCMessageSubscriberService, self).__singleton_init__(
|
||||
def __init__(self, socket_path, io_loop=None):
|
||||
super(IPCMessageSubscriberService, self).__init__(
|
||||
socket_path, io_loop=io_loop)
|
||||
self.saved_data = []
|
||||
self._read_in_progress = Lock()
|
||||
self.handlers = weakref.WeakSet()
|
||||
self.read_stream_future = None
|
||||
|
||||
def _subscribe(self, handler):
|
||||
self.handlers.add(handler)
|
||||
|
@ -670,16 +617,16 @@ class IPCMessageSubscriberService(IPCClient):
|
|||
if timeout is None:
|
||||
timeout = 5
|
||||
|
||||
read_stream_future = None
|
||||
self.read_stream_future = None
|
||||
while self._has_subscribers():
|
||||
if read_stream_future is None:
|
||||
read_stream_future = self.stream.read_bytes(4096, partial=True)
|
||||
if self.read_stream_future is None:
|
||||
self.read_stream_future = self.stream.read_bytes(4096, partial=True)
|
||||
|
||||
try:
|
||||
wire_bytes = yield FutureWithTimeout(self.io_loop,
|
||||
read_stream_future,
|
||||
self.read_stream_future,
|
||||
timeout)
|
||||
read_stream_future = None
|
||||
self.read_stream_future = None
|
||||
|
||||
self.unpacker.feed(wire_bytes)
|
||||
msgs = [msg['body'] for msg in self.unpacker]
|
||||
|
@ -694,6 +641,7 @@ class IPCMessageSubscriberService(IPCClient):
|
|||
break
|
||||
except Exception as exc:
|
||||
log.error('Exception occurred in Subscriber while handling stream: %s', exc)
|
||||
exc = IPCExceptionProxy(sys.exc_info())
|
||||
self._feed_subscribers([exc])
|
||||
break
|
||||
|
||||
|
@ -718,7 +666,7 @@ class IPCMessageSubscriberService(IPCClient):
|
|||
except Exception as exc:
|
||||
log.error('Exception occurred while Subscriber connecting: %s', exc)
|
||||
yield tornado.gen.sleep(1)
|
||||
self._read(timeout)
|
||||
yield self._read(timeout)
|
||||
|
||||
def close(self):
|
||||
'''
|
||||
|
@ -726,8 +674,11 @@ class IPCMessageSubscriberService(IPCClient):
|
|||
Sockets and filehandles should be closed explicitly, to prevent
|
||||
leaks.
|
||||
'''
|
||||
if not self._closing:
|
||||
super(IPCMessageSubscriberService, self).close()
|
||||
super(IPCMessageSubscriberService, self).close()
|
||||
if self.read_stream_future is not None and self.read_stream_future.done():
|
||||
exc = self.read_stream_future.exception()
|
||||
if exc and not isinstance(exc, tornado.iostream.StreamClosedError):
|
||||
log.error("Read future returned exception %r", exc)
|
||||
|
||||
def __del__(self):
|
||||
if IPCMessageSubscriberService in globals():
|
||||
|
@ -801,8 +752,8 @@ class IPCMessageSubscriber(object):
|
|||
raise tornado.gen.Return(None)
|
||||
if data is None:
|
||||
break
|
||||
elif isinstance(data, Exception):
|
||||
raise data
|
||||
elif isinstance(data, IPCExceptionProxy):
|
||||
six.reraise(*data.orig_info)
|
||||
elif callback:
|
||||
self.service.io_loop.spawn_callback(callback, data)
|
||||
else:
|
||||
|
@ -821,6 +772,7 @@ class IPCMessageSubscriber(object):
|
|||
|
||||
def close(self):
|
||||
self.service.unsubscribe(self)
|
||||
self.service.close()
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
|
|
@ -34,7 +34,7 @@ import salt.transport.client
|
|||
import salt.transport.server
|
||||
import salt.transport.mixins.auth
|
||||
from salt.ext import six
|
||||
from salt.exceptions import SaltReqTimeoutError
|
||||
from salt.exceptions import SaltReqTimeoutError, SaltException
|
||||
from salt._compat import ipaddress
|
||||
|
||||
from salt.utils.zeromq import zmq, ZMQDefaultLoop, install_zmq, ZMQ_VERSION_INFO, LIBZMQ_VERSION_INFO
|
||||
|
@ -260,12 +260,18 @@ class AsyncZeroMQReqChannel(salt.transport.client.ReqChannel):
|
|||
|
||||
@property
|
||||
def master_uri(self):
|
||||
if 'master_uri' in self.opts:
|
||||
return self.opts['master_uri']
|
||||
|
||||
# if by chance master_uri is not there..
|
||||
if 'master_ip' in self.opts:
|
||||
return _get_master_uri(self.opts['master_ip'],
|
||||
self.opts['master_port'],
|
||||
source_ip=self.opts.get('source_ip'),
|
||||
source_port=self.opts.get('source_ret_port'))
|
||||
return self.opts['master_uri']
|
||||
|
||||
# if we've reached here something is very abnormal
|
||||
raise SaltException('ReqChannel: missing master_uri/master_ip in self.opts')
|
||||
|
||||
def _package_load(self, load):
|
||||
return {
|
||||
|
|
3
tests/integration/files/conf/master.d/peers.conf
Normal file
3
tests/integration/files/conf/master.d/peers.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
peer:
|
||||
.*:
|
||||
- x509.sign_remote_certificate
|
65
tests/integration/files/file/base/test_cert.sls
Normal file
65
tests/integration/files/file/base/test_cert.sls
Normal file
|
@ -0,0 +1,65 @@
|
|||
{% set tmp_dir = pillar['tmp_dir'] %}
|
||||
|
||||
{{ tmp_dir }}/pki:
|
||||
file.directory
|
||||
|
||||
{{ tmp_dir }}/pki/issued_certs:
|
||||
file.directory
|
||||
|
||||
{{ tmp_dir }}/pki/ca.key:
|
||||
x509.private_key_managed:
|
||||
- bits: 4096
|
||||
- require:
|
||||
- file: {{ tmp_dir }}/pki
|
||||
|
||||
{{ tmp_dir }}/pki/ca.crt:
|
||||
x509.certificate_managed:
|
||||
- signing_private_key: {{ tmp_dir }}/pki/ca.key
|
||||
- CN: ca.example.com
|
||||
- C: US
|
||||
- ST: Utah
|
||||
- L: Salt Lake City
|
||||
- basicConstraints: "critical CA:true"
|
||||
- keyUsage: "critical cRLSign, keyCertSign"
|
||||
- subjectKeyIdentifier: hash
|
||||
- authorityKeyIdentifier: keyid,issuer:always
|
||||
- days_valid: 3650
|
||||
- days_remaining: 0
|
||||
- backup: True
|
||||
- managed_private_key:
|
||||
name: {{ tmp_dir }}/pki/ca.key
|
||||
bits: 4096
|
||||
backup: True
|
||||
- require:
|
||||
- file: {{ tmp_dir }}/pki
|
||||
- {{ tmp_dir }}/pki/ca.key
|
||||
|
||||
mine.send:
|
||||
module.run:
|
||||
- func: x509.get_pem_entries
|
||||
- kwargs:
|
||||
glob_path: {{ tmp_dir }}/pki/ca.crt
|
||||
- onchanges:
|
||||
- x509: {{ tmp_dir }}/pki/ca.crt
|
||||
|
||||
{{ tmp_dir }}/pki/test.key:
|
||||
x509.private_key_managed:
|
||||
- bits: 4096
|
||||
- backup: True
|
||||
|
||||
test_crt:
|
||||
x509.certificate_managed:
|
||||
- name: {{ tmp_dir }}/pki/test.crt
|
||||
- ca_server: minion
|
||||
- signing_policy: ca_policy
|
||||
- public_key: {{ tmp_dir }}/pki/test.key
|
||||
- CN: minion
|
||||
- days_remaining: 30
|
||||
- backup: True
|
||||
- managed_private_key:
|
||||
name: {{ tmp_dir }}/pki/test.key
|
||||
bits: 4096
|
||||
backup: True
|
||||
- require:
|
||||
- {{ tmp_dir }}/pki/ca.crt
|
||||
- {{ tmp_dir }}/pki/test.key
|
|
@ -459,6 +459,21 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
changes = next(six.itervalues(ret))['changes']
|
||||
self.assertEqual('<show_changes=False>', changes['diff'])
|
||||
|
||||
def test_managed_show_changes_true(self):
|
||||
'''
|
||||
file.managed test interface
|
||||
'''
|
||||
name = os.path.join(TMP, 'grail_not_scene33')
|
||||
with salt.utils.files.fopen(name, 'wb') as fp_:
|
||||
fp_.write(b'test_managed_show_changes_false\n')
|
||||
|
||||
ret = self.run_state(
|
||||
'file.managed', name=name, source='salt://grail/scene33',
|
||||
)
|
||||
|
||||
changes = next(six.itervalues(ret))['changes']
|
||||
self.assertIn('diff', changes)
|
||||
|
||||
@skipIf(IS_WINDOWS, 'Don\'t know how to fix for Windows')
|
||||
def test_managed_escaped_file_path(self):
|
||||
'''
|
||||
|
|
|
@ -5,9 +5,10 @@ import logging
|
|||
|
||||
import salt.utils.files
|
||||
from salt.ext import six
|
||||
import textwrap
|
||||
|
||||
from tests.support.helpers import with_tempfile
|
||||
from tests.support.paths import BASE_FILES
|
||||
from tests.support.paths import BASE_FILES, TMP, TMP_PILLAR_TREE
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.unit import skipIf
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
|
@ -31,6 +32,36 @@ class x509Test(ModuleCase, SaltReturnAssertsMixin):
|
|||
with salt.utils.files.fopen(cert_path) as fp:
|
||||
cls.x509_cert_text = fp.read()
|
||||
|
||||
def setUp(self):
|
||||
with salt.utils.files.fopen(os.path.join(TMP_PILLAR_TREE, 'signing_policies.sls'), 'w') as fp:
|
||||
fp.write(textwrap.dedent('''\
|
||||
x509_signing_policies:
|
||||
ca_policy:
|
||||
- minions: '*'
|
||||
- signing_private_key: {0}/pki/ca.key
|
||||
- signing_cert: {0}/pki/ca.crt
|
||||
- O: Test Company
|
||||
- basicConstraints: "CA:false"
|
||||
- keyUsage: "critical digitalSignature, keyEncipherment"
|
||||
- extendedKeyUsage: "critical serverAuth, clientAuth"
|
||||
- subjectKeyIdentifier: hash
|
||||
- authorityKeyIdentifier: keyid
|
||||
- days_valid: 730
|
||||
- copypath: {0}/pki
|
||||
'''.format(TMP)))
|
||||
with salt.utils.files.fopen(os.path.join(TMP_PILLAR_TREE, 'top.sls'), 'w') as fp:
|
||||
fp.write(textwrap.dedent('''\
|
||||
base:
|
||||
'*':
|
||||
- signing_policies
|
||||
'''))
|
||||
self.run_function('saltutil.refresh_pillar')
|
||||
|
||||
def tearDown(self):
|
||||
os.remove(os.path.join(TMP_PILLAR_TREE, 'signing_policies.sls'))
|
||||
os.remove(os.path.join(TMP_PILLAR_TREE, 'top.sls'))
|
||||
self.run_function('saltutil.refresh_pillar')
|
||||
|
||||
def run_function(self, *args, **kwargs):
|
||||
ret = super(x509Test, self).run_function(*args, **kwargs)
|
||||
log.debug('ret = %s', ret)
|
||||
|
@ -61,3 +92,11 @@ class x509Test(ModuleCase, SaltReturnAssertsMixin):
|
|||
assert state_result['result'] is True, state_result
|
||||
assert os.path.exists(keyfile)
|
||||
assert os.path.exists(crtfile)
|
||||
|
||||
def test_cert_signing(self):
|
||||
ret = self.run_function('state.apply', ['test_cert'], pillar={'tmp_dir': TMP})
|
||||
key = 'x509_|-test_crt_|-{}/pki/test.crt_|-certificate_managed'.format(TMP)
|
||||
assert key in ret
|
||||
assert 'changes' in ret[key]
|
||||
assert 'Certificate' in ret[key]['changes']
|
||||
assert 'New' in ret[key]['changes']['Certificate']
|
||||
|
|
|
@ -136,6 +136,28 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
|||
os_release = core._parse_os_release('/etc/os-release', '/usr/lib/os-release')
|
||||
self.assertEqual(os_release, {})
|
||||
|
||||
@skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
|
||||
def test__windows_platform_data(self):
|
||||
grains = core._windows_platform_data()
|
||||
keys = ['biosversion',
|
||||
'osrelease',
|
||||
'domain',
|
||||
'kernelrelease',
|
||||
'motherboard',
|
||||
'serialnumber',
|
||||
'timezone',
|
||||
'manufacturer',
|
||||
'kernelversion',
|
||||
'osservicepack',
|
||||
'virtual',
|
||||
'productname',
|
||||
'osfullname',
|
||||
'osmanufacturer',
|
||||
'osversion',
|
||||
'windowsdomain']
|
||||
for key in keys:
|
||||
self.assertIn(key, grains)
|
||||
|
||||
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
||||
def test_gnu_slash_linux_in_os_name(self):
|
||||
'''
|
||||
|
|
|
@ -197,9 +197,12 @@ class SampleConfTest(TestCase):
|
|||
commented out. This test loops through all of the files in that directory to check
|
||||
for any lines that are not commented or blank.
|
||||
'''
|
||||
cloud_sample_files = os.listdir(SAMPLE_CONF_DIR + 'cloud.profiles.d/')
|
||||
cloud_sample_dir = SAMPLE_CONF_DIR + 'cloud.profiles.d/'
|
||||
if not os.path.exists(cloud_sample_dir):
|
||||
self.skipTest("Sample config directory '{}' is missing.".format(cloud_sample_dir))
|
||||
cloud_sample_files = os.listdir(cloud_sample_dir)
|
||||
for conf_file in cloud_sample_files:
|
||||
profile_conf = SAMPLE_CONF_DIR + 'cloud.profiles.d/' + conf_file
|
||||
profile_conf = cloud_sample_dir + conf_file
|
||||
ret = salt.config._read_conf_file(profile_conf)
|
||||
self.assertEqual(
|
||||
ret,
|
||||
|
@ -215,9 +218,12 @@ class SampleConfTest(TestCase):
|
|||
commented out. This test loops through all of the files in that directory to check
|
||||
for any lines that are not commented or blank.
|
||||
'''
|
||||
cloud_sample_files = os.listdir(SAMPLE_CONF_DIR + 'cloud.providers.d/')
|
||||
cloud_sample_dir = SAMPLE_CONF_DIR + 'cloud.providers.d/'
|
||||
if not os.path.exists(cloud_sample_dir):
|
||||
self.skipTest("Sample config directory '{}' is missing.".format(cloud_sample_dir))
|
||||
cloud_sample_files = os.listdir(cloud_sample_dir)
|
||||
for conf_file in cloud_sample_files:
|
||||
provider_conf = SAMPLE_CONF_DIR + 'cloud.providers.d/' + conf_file
|
||||
provider_conf = cloud_sample_dir + conf_file
|
||||
ret = salt.config._read_conf_file(provider_conf)
|
||||
self.assertEqual(
|
||||
ret,
|
||||
|
@ -233,9 +239,12 @@ class SampleConfTest(TestCase):
|
|||
commented out. This test loops through all of the files in that directory to check
|
||||
for any lines that are not commented or blank.
|
||||
'''
|
||||
cloud_sample_files = os.listdir(SAMPLE_CONF_DIR + 'cloud.maps.d/')
|
||||
cloud_sample_dir = SAMPLE_CONF_DIR + 'cloud.maps.d/'
|
||||
if not os.path.exists(cloud_sample_dir):
|
||||
self.skipTest("Sample config directory '{}' is missing.".format(cloud_sample_dir))
|
||||
cloud_sample_files = os.listdir(cloud_sample_dir)
|
||||
for conf_file in cloud_sample_files:
|
||||
map_conf = SAMPLE_CONF_DIR + 'cloud.maps.d/' + conf_file
|
||||
map_conf = cloud_sample_dir + conf_file
|
||||
ret = salt.config._read_conf_file(map_conf)
|
||||
self.assertEqual(
|
||||
ret,
|
||||
|
|
|
@ -86,13 +86,14 @@ class IPCMessageClient(BaseIPCReqCase):
|
|||
'''
|
||||
|
||||
def _get_channel(self):
|
||||
channel = salt.transport.ipc.IPCMessageClient(
|
||||
socket_path=self.socket_path,
|
||||
io_loop=self.io_loop,
|
||||
)
|
||||
channel.connect(callback=self.stop)
|
||||
self.wait()
|
||||
return channel
|
||||
if not hasattr(self, 'channel') or self.channel is None:
|
||||
self.channel = salt.transport.ipc.IPCMessageClient(
|
||||
socket_path=self.socket_path,
|
||||
io_loop=self.io_loop,
|
||||
)
|
||||
self.channel.connect(callback=self.stop)
|
||||
self.wait()
|
||||
return self.channel
|
||||
|
||||
def setUp(self):
|
||||
super(IPCMessageClient, self).setUp()
|
||||
|
@ -107,6 +108,8 @@ class IPCMessageClient(BaseIPCReqCase):
|
|||
if exc.errno != errno.EBADF:
|
||||
# If its not a bad file descriptor error, raise
|
||||
raise
|
||||
finally:
|
||||
self.channel = None
|
||||
|
||||
def test_singleton(self):
|
||||
channel = self._get_channel()
|
||||
|
@ -120,23 +123,6 @@ class IPCMessageClient(BaseIPCReqCase):
|
|||
self.wait()
|
||||
self.assertEqual(self.payloads[0], msg)
|
||||
|
||||
def test_last_singleton_instance_closes(self):
|
||||
channel = self._get_channel()
|
||||
msg = {'foo': 'bar', 'stop': True}
|
||||
log.debug('Sending msg1')
|
||||
self.channel.send(msg)
|
||||
self.wait()
|
||||
self.assertEqual(self.payloads[0], msg)
|
||||
channel.close()
|
||||
# Since this is a singleton, and only the last singleton instance
|
||||
# should actually close the connection, the next code should still
|
||||
# work and not timeout
|
||||
msg = {'bar': 'foo', 'stop': True}
|
||||
log.debug('Sending msg2')
|
||||
self.channel.send(msg)
|
||||
self.wait()
|
||||
self.assertEqual(self.payloads[1], msg)
|
||||
|
||||
def test_basic_send(self):
|
||||
msg = {'foo': 'bar', 'stop': True}
|
||||
self.channel.send(msg)
|
||||
|
|
|
@ -145,6 +145,17 @@ class ClearReqTestCases(BaseZMQReqCase, ReqChannelMixin):
|
|||
'''
|
||||
raise tornado.gen.Return((payload, {'fun': 'send_clear'}))
|
||||
|
||||
def test_master_uri_override(self):
|
||||
'''
|
||||
ensure master_uri kwarg is respected
|
||||
'''
|
||||
# minion_config should be 127.0.0.1, we want a different uri that still connects
|
||||
uri = 'tcp://{master_ip}:{master_port}'.format(master_ip='localhost', master_port=self.minion_config['master_port'])
|
||||
|
||||
channel = salt.transport.Channel.factory(self.minion_config, master_uri=uri)
|
||||
self.assertIn('localhost', channel.master_uri)
|
||||
del channel
|
||||
|
||||
|
||||
@flaky
|
||||
@skipIf(ON_SUSE, 'Skipping until https://github.com/saltstack/salt/issues/32902 gets fixed')
|
||||
|
|
|
@ -14,7 +14,7 @@ import shutil
|
|||
from datetime import date
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.unit import TestCase
|
||||
from tests.support.unit import TestCase, skipIf
|
||||
from tests.support.mock import MagicMock, patch
|
||||
|
||||
# Import salt libs
|
||||
|
@ -35,6 +35,8 @@ class ExtendTestCase(TestCase):
|
|||
shutil.rmtree(self.out, True)
|
||||
os.chdir(self.starting_dir)
|
||||
|
||||
@skipIf(not os.path.exists(os.path.join(integration.CODE_DIR, 'templates')),
|
||||
"Test template directory 'templates/' missing.")
|
||||
def test_run(self):
|
||||
with patch('sys.exit', MagicMock):
|
||||
out = salt.utils.extend.run('test', 'test', 'this description', integration.CODE_DIR, False)
|
||||
|
|
Loading…
Add table
Reference in a new issue