Merge branch 'nitrogen' into 'develop'

Conflicts:
  - salt/states/keystone.py
This commit is contained in:
rallytime 2017-06-06 12:50:35 -06:00
commit 2cb4f2baa9
32 changed files with 264 additions and 97 deletions

View File

@ -1584,6 +1584,7 @@ class LocalClient(object):
expect_minions=(verbose or show_timeout),
**kwargs
):
log.debug('return event: %s', ret)
return_count = return_count + 1
if progress:
for id_, min_ret in six.iteritems(ret):

View File

@ -42,12 +42,12 @@ Example of usage
.. code:: txt
08:33:57 @gtmanfred » !ping
08:33:57 gtmanbot » gtmanfred: pong
08:34:02 @gtmanfred » !echo ping
08:34:02 gtmanbot » ping
08:34:17 @gtmanfred » !event test/tag/ircbot irc is usefull
08:34:17 gtmanbot » gtmanfred: TaDa!
08:33:57 @gtmanfred > !ping
08:33:57 gtmanbot > gtmanfred: pong
08:34:02 @gtmanfred > !echo ping
08:34:02 gtmanbot > ping
08:34:17 @gtmanfred > !event test/tag/ircbot irc is usefull
08:34:17 gtmanbot > gtmanfred: TaDa!
.. code:: txt

View File

@ -28,7 +28,7 @@ of the following fields:
10. raw (the raw event data forwarded from the device)
The topic title can consist of any of the combination of above fields,
but the topic has to start with jnpr/syslog.
but the topic has to start with 'jnpr/syslog'.
So, we can have different combinations:
- jnpr/syslog/hostip/daemon/event
- jnpr/syslog/daemon/severity
@ -37,7 +37,7 @@ The corresponding dynamic topic sent on salt event bus would look something like
- jnpr/syslog/1.1.1.1/mgd/UI_COMMIT_COMPLETED
- jnpr/syslog/sshd/7
The default topic title is jnpr/syslog/hostname/event.
The default topic title is 'jnpr/syslog/hostname/event'.
The user can choose the type of data he/she wants of the event bus.
Like, if one wants only events pertaining to a particular daemon, he/she can

View File

@ -592,20 +592,37 @@ class Client(object):
destfp = None
try:
# Tornado calls streaming_callback on redirect response bodies.
# But we need streaming to support fetching large files (> RAM avail).
# Here we working this around by disabling recording the body for redirections.
# The issue is fixed in Tornado 4.3.0 so on_header callback could be removed
# when we'll deprecate Tornado<4.3.0.
# See #27093 and #30431 for details.
# But we need streaming to support fetching large files (> RAM
# avail). Here we are working around this by disabling recording
# the body for redirections. The issue is fixed in Tornado 4.3.0
# so on_header callback could be removed when we'll deprecate
# Tornado<4.3.0. See #27093 and #30431 for details.
# Use list here to make it writable inside the on_header callback. Simple bool doesn't
# work here: on_header creates a new local variable instead. This could be avoided in
# Py3 with 'nonlocal' statement. There is no Py2 alternative for this.
# Use list here to make it writable inside the on_header callback.
# Simple bool doesn't work here: on_header creates a new local
# variable instead. This could be avoided in Py3 with 'nonlocal'
# statement. There is no Py2 alternative for this.
#
# write_body[0] is used by the on_chunk callback to tell it whether
# or not we need to write the body of the request to disk. For
# 30x redirects we set this to False because we don't want to
# write the contents to disk, as we will need to wait until we
# get to the redirected URL.
#
# write_body[1] will contain a tornado.httputil.HTTPHeaders
# instance that we will use to parse each header line. We
# initialize this to False, and after we parse the status line we
# will replace it with the HTTPHeaders instance. If/when we have
# found the encoding used in the request, we set this value to
# False to signify that we are done parsing.
#
# write_body[2] is where the encoding will be stored
write_body = [None, False, None]
def on_header(hdr):
if write_body[1] is not False and write_body[2] is None:
# Try to find out what content type encoding is used if this is a text file
# Try to find out what content type encoding is used if
# this is a text file
write_body[1].parse_line(hdr) # pylint: disable=no-member
if 'Content-Type' in write_body[1]:
content_type = write_body[1].get('Content-Type') # pylint: disable=no-member
@ -621,17 +638,22 @@ class Client(object):
# We have found our encoding. Stop processing headers.
write_body[1] = False
if write_body[0] is not None:
# We already parsed the first line. No need to run the code below again
return
# If write_body[0] is False, this means that this
# header is a 30x redirect, so we need to reset
# write_body[0] to None so that we parse the HTTP
# status code from the redirect target.
if write_body[0] is write_body[1] is False:
write_body[0] = None
try:
hdr = parse_response_start_line(hdr)
except HTTPInputError:
# Not the first line, do nothing
return
write_body[0] = hdr.code not in [301, 302, 303, 307]
write_body[1] = HTTPHeaders()
# Check the status line of the HTTP request
if write_body[0] is None:
try:
hdr = parse_response_start_line(hdr)
except HTTPInputError:
# Not the first line, do nothing
return
write_body[0] = hdr.code not in [301, 302, 303, 307]
write_body[1] = HTTPHeaders()
if no_cache:
result = []

View File

@ -1538,6 +1538,7 @@ class Minion(MinionBase):
else:
data['ret'] = opts['return']
log.debug('minion return: %s', ret)
# TODO: make a list? Seems odd to split it this late :/
if data['ret'] and isinstance(data['ret'], six.string_types):
if 'ret_config' in data:

View File

@ -296,7 +296,7 @@ def ec2_credentials_list(user_id=None, name=None, profile=None,
return ret
def endpoint_get(service, region=None, profile=None, **connection_args):
def endpoint_get(service, region=None, profile=None, interface=None, **connection_args):
'''
Return a specific endpoint (keystone endpoint-get)
@ -304,7 +304,9 @@ def endpoint_get(service, region=None, profile=None, **connection_args):
.. code-block:: bash
salt '*' keystone.endpoint_get nova [region=RegionOne]
salt 'v2' keystone.endpoint_get nova [region=RegionOne]
salt 'v3' keystone.endpoint_get nova interface=admin [region=RegionOne]
'''
auth(profile, **connection_args)
services = service_list(profile, **connection_args)
@ -315,12 +317,13 @@ def endpoint_get(service, region=None, profile=None, **connection_args):
e = [_f for _f in [e
if e['service_id'] == service_id and
(e['region'] == region if region else True) else None for e in endpoints.values()] if _f]
(e['region'] == region if region else True) and
(e['interface'] == interface if interface else True)
else None for e in endpoints.values()] if _f]
if len(e) > 1:
return {'Error': 'Multiple endpoints found ({0}) for the {1} service. Please specify region.'.format(e, service)}
if len(e) == 1:
return e[0]
#log.debug('Could not find endpoint for the specified service {0}, service_id: {3} and region {1} in endpoints {2}'.format(service, region, endpoints.values(), service_id))
return {'Error': 'Could not find endpoint for the specified service'}
@ -374,10 +377,10 @@ def endpoint_create(service, publicurl=None, internalurl=None, adminurl=None,
publicurl=publicurl,
adminurl=adminurl,
internalurl=internalurl)
return endpoint_get(service, region, profile, **connection_args)
return endpoint_get(service, region, profile, interface, **connection_args)
def endpoint_delete(service, region=None, profile=None, **connection_args):
def endpoint_delete(service, region=None, profile=None, interface=None, **connection_args):
'''
Delete endpoints of an Openstack service
@ -385,14 +388,16 @@ def endpoint_delete(service, region=None, profile=None, **connection_args):
.. code-block:: bash
salt '*' keystone.endpoint_delete nova [region=RegionOne]
salt 'v2' keystone.endpoint_delete nova [region=RegionOne]
salt 'v3' keystone.endpoint_delete nova interface=admin [region=RegionOne]
'''
kstone = auth(profile, **connection_args)
endpoint = endpoint_get(service, region, profile, **connection_args)
endpoint = endpoint_get(service, region, profile, interface, **connection_args)
if not endpoint or 'Error' in endpoint:
return {'Error': 'Could not find any endpoints for the service'}
kstone.endpoints.delete(endpoint['id'])
endpoint = endpoint_get(service, region, profile, **connection_args)
endpoint = endpoint_get(service, region, profile, interface, **connection_args)
if not endpoint or 'Error' in endpoint:
return True

View File

@ -117,8 +117,12 @@ def bin_pkg_info(path, saltenv='base'):
output,
osarch=__grains__['osarch']
)
for field in pkginfo._fields:
ret[field] = getattr(pkginfo, field)
try:
for field in pkginfo._fields:
ret[field] = getattr(pkginfo, field)
except AttributeError:
# pkginfo is None
return None
return ret

View File

@ -5,6 +5,7 @@ Module for running arbitrary tests
from __future__ import absolute_import
# Import Python libs
import logging
import os
import sys
import time
@ -27,6 +28,8 @@ __func_alias__ = {
'false_': 'false'
}
log = logging.getLogger(__name__)
@depends('non_existantmodulename')
def missing_func():
@ -112,6 +115,7 @@ def ping():
'''
if not salt.utils.is_proxy():
log.debug('test.ping received for minion \'%s\'', __opts__.get('id'))
return True
else:
ping_cmd = __opts__['proxy']['proxytype'] + '.ping'

View File

@ -981,21 +981,24 @@ def create_crl( # pylint: disable=too-many-arguments,too-many-locals
OpenSSL.crypto.FILETYPE_PEM,
get_pem_entry(signing_private_key))
export_kwargs = {
'cert': cert,
'key': key,
'type': OpenSSL.crypto.FILETYPE_PEM,
'days': days_valid
}
if digest:
export_kwargs['digest'] = bytes(digest)
else:
log.warning('No digest specified. The default md5 digest will be used.')
try:
crltext = crl.export(
cert,
key,
OpenSSL.crypto.FILETYPE_PEM,
days=days_valid,
digest=bytes(digest))
except TypeError:
crltext = crl.export(**export_kwargs)
except (TypeError, ValueError):
log.warning(
'Error signing crl with specified digest. Are you using pyopenssl 0.15 or newer? The default md5 digest will be used.')
crltext = crl.export(
cert,
key,
OpenSSL.crypto.FILETYPE_PEM,
days=days_valid)
export_kwargs.pop('digest', None)
crltext = crl.export(**export_kwargs)
if text:
return crltext

View File

@ -82,10 +82,10 @@ from __future__ import absolute_import
import yaml
import pprint
import logging
import urllib
# pylint: disable=import-error,no-name-in-module,redefined-builtin
import salt.ext.six.moves.http_client
from salt.ext.six.moves.urllib.parse import urlencode as _urlencode
# pylint: enable=import-error,no-name-in-module,redefined-builtin
# Import Salt Libs
@ -168,7 +168,7 @@ def _post_message(channel,
api_key=api_key,
method='POST',
header_dict={'Content-Type': 'application/x-www-form-urlencoded'},
data=urllib.urlencode(parameters))
data=_urlencode(parameters))
log.debug('result {0}'.format(result))
if result:

View File

@ -55,7 +55,6 @@ def _ping(tgt, tgt_type, timeout, gather_job_timeout):
tgt_type,
gather_job_timeout=gather_job_timeout):
log.debug('fn_ret: %s', fn_ret)
if fn_ret:
for mid, _ in six.iteritems(fn_ret):
log.debug('minion \'%s\' returned from ping', mid)

View File

@ -24,6 +24,7 @@ from salt.ext.six.moves.urllib.parse import urlparse as _urlparse # pylint: dis
# Import salt libs
import salt.utils
import salt.utils.files
import salt.utils.url
from salt.exceptions import CommandExecutionError, CommandNotFoundError
log = logging.getLogger(__name__)
@ -888,7 +889,9 @@ def extracted(name,
ret['result'] = None
ret['comment'] = (
'Archive {0} would be downloaded to cache and checked to '
'discover if extraction is necessary'.format(source_match)
'discover if extraction is necessary'.format(
salt.utils.url.redact_http_basic_auth(source_match)
)
)
return ret
@ -918,18 +921,27 @@ def extracted(name,
try:
if not file_result['result']:
log.debug('failed to download {0}'.format(source_match))
log.debug(
'failed to download %s',
salt.utils.url.redact_http_basic_auth(source_match)
)
return file_result
except TypeError:
if not file_result:
log.debug('failed to download {0}'.format(source_match))
log.debug(
'failed to download %s',
salt.utils.url.redact_http_basic_auth(source_match)
)
return file_result
if source_hash:
_update_checksum(cached_source)
else:
log.debug('Archive %s is already in cache', source_match)
log.debug(
'Archive %s is already in cache',
salt.utils.url.redact_http_basic_auth(source_match)
)
if archive_format == 'zip' and not password:
log.debug('Checking %s to see if it is password-protected',
@ -950,7 +962,7 @@ def extracted(name,
ret['comment'] = (
'Archive {0} is password-protected, but no password was '
'specified. Please set the \'password\' argument.'.format(
source_match
salt.utils.url.redact_http_basic_auth(source_match)
)
)
return ret
@ -1138,7 +1150,7 @@ def extracted(name,
ret['result'] = None
ret['comment'] = \
'Archive {0} would be extracted to {1}'.format(
source_match,
salt.utils.url.redact_http_basic_auth(source_match),
name
)
if clean and contents is not None:
@ -1421,13 +1433,18 @@ def extracted(name,
if created_destdir:
ret['changes']['directories_created'] = [name]
ret['changes']['extracted_files'] = files
ret['comment'] = '{0} extracted to {1}'.format(source_match, name)
ret['comment'] = '{0} extracted to {1}'.format(
salt.utils.url.redact_http_basic_auth(source_match),
name,
)
_add_explanation(ret, source_hash_trigger, contents_missing)
ret['result'] = True
else:
ret['result'] = False
ret['comment'] = 'Can\'t extract content of {0}'.format(source_match)
ret['comment'] = 'No files were extracted from {0}'.format(
salt.utils.url.redact_http_basic_auth(source_match)
)
else:
ret['result'] = True
if if_missing_path_exists:

View File

@ -656,6 +656,7 @@ def endpoint_present(name,
endpoint = __salt__['keystone.endpoint_get'](name, region,
profile=profile,
interface=interface,
**connection_args)
def _changes(desc):
@ -750,7 +751,7 @@ def endpoint_present(name,
ret['changes']['internalurl'] = internalurl
if ret['comment']: # changed
__salt__['keystone.endpoint_delete'](name, region, profile=profile, **connection_args)
__salt__['keystone.endpoint_delete'](name, region, profile=profile, interface=interface, **connection_args)
_create_endpoint()
ret['comment'] += 'Endpoint for service "{0}" has been updated'.format(name)
@ -765,26 +766,34 @@ def endpoint_present(name,
ret['comment'] = 'Endpoint for service "{0}" has been added'.format(name)
if ret['comment'] == '': # => no changes
ret['result'] = None
ret['comment'] = 'Endpoint for service "{0}" already exists'.format(name)
return ret
def endpoint_absent(name, region=None, profile=None, **connection_args):
def endpoint_absent(name, region=None, profile=None, interface=None, **connection_args):
'''
Ensure that the endpoint for a service doesn't exist in Keystone catalog
name
The name of the service whose endpoints should not exist
region (optional)
The region of the endpoint. Defaults to ``RegionOne``.
interface
The interface type, which describes the visibility
of the endpoint. (for V3 API)
'''
ret = {'name': name,
'changes': {},
'result': True,
'comment': 'Endpoint for service "{0}" is already absent'.format(name)}
'comment': 'Endpoint for service "{0}"{1} is already absent'.format(name,
', interface "{0}",'.format(interface) if interface is not None else '')}
# Check if service is present
endpoint = __salt__['keystone.endpoint_get'](name, region,
profile=profile,
interface=interface,
**connection_args)
if not endpoint:
return ret
@ -796,7 +805,9 @@ def endpoint_absent(name, region=None, profile=None, **connection_args):
# Delete service
__salt__['keystone.endpoint_delete'](name, region,
profile=profile,
interface=interface,
**connection_args)
ret['comment'] = 'Endpoint for service "{0}" has been deleted'.format(name)
ret['comment'] = 'Endpoint for service "{0}"{1} has been deleted'.format(name,
', interface "{0}",'.format(interface) if interface is not None else '')
ret['changes']['endpoint'] = 'Deleted'
return ret

View File

@ -784,10 +784,13 @@ def _find_install_targets(name=None,
' and are at the desired version' if version_spec and not sources
else ''
)
return {'name': name,
'changes': {},
'result': True,
'comment': msg}
ret = {'name': name,
'changes': {},
'result': True,
'comment': msg}
if warnings:
ret.setdefault('warnings', []).extend(warnings)
return ret
return (desired, targets, to_unpurge, to_reinstall, altered_files,
warnings, was_refreshed)
@ -1529,7 +1532,7 @@ def installed(
'result': False,
'comment': 'lowpkg.unpurge not implemented'}
if warnings:
ret['comment'] += '.' + '. '.join(warnings) + '.'
ret.setdefault('warnings', []).extend(warnings)
return ret
# Remove any targets not returned by _find_install_targets
@ -1592,7 +1595,7 @@ def installed(
'result': None,
'comment': '\n'.join(comment)}
if warnings:
ret['comment'] += '\n' + '. '.join(warnings) + '.'
ret.setdefault('warnings', []).extend(warnings)
return ret
changes = {'installed': {}}
@ -1627,7 +1630,7 @@ def installed(
ret['comment'] = ('An error was encountered while installing '
'package(s): {0}'.format(exc))
if warnings:
ret['comment'] += '\n\n' + '. '.join(warnings) + '.'
ret.setdefault('warnings', []).extend(warnings)
return ret
if refresh:
@ -1662,7 +1665,7 @@ def installed(
'result': False,
'comment': '\n'.join(comment)}
if warnings:
ret['comment'] += '.' + '. '.join(warnings) + '.'
ret.setdefault('warnings', []).extend(warnings)
return ret
else:
if 'result' in hold_ret and not hold_ret['result']:
@ -1673,7 +1676,7 @@ def installed(
'holding/unholding package(s): {0}'
.format(hold_ret['comment'])}
if warnings:
ret['comment'] += '.' + '. '.join(warnings) + '.'
ret.setdefault('warnings', []).extend(warnings)
return ret
else:
modified_hold = [hold_ret[x] for x in hold_ret
@ -1863,7 +1866,7 @@ def installed(
'result': result,
'comment': '\n'.join(comment)}
if warnings:
ret['comment'] += '\n' + '. '.join(warnings) + '.'
ret.setdefault('warnings', []).extend(warnings)
return ret

View File

@ -14,7 +14,6 @@ import logging
import os.path
import pprint
import socket
import urllib
import yaml
import ssl
@ -55,6 +54,7 @@ import salt.ext.six.moves.http_cookiejar
import salt.ext.six.moves.urllib.request as urllib_request
from salt.ext.six.moves.urllib.error import URLError
from salt.ext.six.moves.urllib.parse import splitquery
from salt.ext.six.moves.urllib.parse import urlencode as _urlencode
# pylint: enable=import-error,no-name-in-module
# Don't need a try/except block, since Salt depends on tornado
@ -438,7 +438,7 @@ def query(url,
'not valid: {0}'.format(cert))
if isinstance(data, dict):
data = urllib.urlencode(data)
data = _urlencode(data)
if verify_ssl:
req_kwargs['ca_certs'] = ca_bundle

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
'''
:copyright: © 2017 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2017 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2015 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2015 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2016 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2016 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -6,15 +6,25 @@ import os
import uuid
import shutil
import hashlib
import logging
import psutil
import shutil
import signal
import tempfile
import textwrap
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.helpers import get_unused_localhost_port, skip_if_not_root
from tests.support.unit import skipIf
import tests.support.paths as paths
# Import salt libs
import salt.ext.six as six
import salt.utils
log = logging.getLogger(__name__)
class CPModuleTest(ModuleCase):
'''
@ -415,6 +425,83 @@ class CPModuleTest(ModuleCase):
with salt.utils.fopen(ret, 'r') as cp_:
self.assertEqual(cp_.read(), 'foo')
@skipIf(not salt.utils.which('nginx'), 'nginx not installed')
@skip_if_not_root
def test_cache_remote_file(self):
'''
cp.cache_file
'''
nginx_port = get_unused_localhost_port()
url_prefix = 'http://localhost:{0}/'.format(nginx_port)
temp_dir = tempfile.mkdtemp(dir=paths.TMP)
self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
nginx_root_dir = os.path.join(temp_dir, 'root')
nginx_conf_dir = os.path.join(temp_dir, 'conf')
nginx_conf = os.path.join(nginx_conf_dir, 'nginx.conf')
nginx_pidfile = os.path.join(nginx_conf_dir, 'nginx.pid')
file_contents = 'Hello world!'
for dirname in (nginx_root_dir, nginx_conf_dir):
os.mkdir(dirname)
# Write the temp file
with salt.utils.fopen(os.path.join(nginx_root_dir, 'actual_file'), 'w') as fp_:
fp_.write(file_contents)
# Write the nginx config
with salt.utils.fopen(nginx_conf, 'w') as fp_:
fp_.write(textwrap.dedent(
'''\
user root;
worker_processes 1;
error_log {nginx_conf_dir}/server_error.log;
pid {nginx_pidfile};
events {{
worker_connections 1024;
}}
http {{
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log {nginx_conf_dir}/access.log;
error_log {nginx_conf_dir}/error.log;
server {{
listen {nginx_port} default_server;
server_name cachefile.local;
root {nginx_root_dir};
location ~ ^/301$ {{
return 301 /actual_file;
}}
location ~ ^/302$ {{
return 302 /actual_file;
}}
}}
}}'''.format(**locals())
))
self.run_function(
'cmd.run',
[['nginx', '-c', nginx_conf]],
python_shell=False
)
with salt.utils.fopen(nginx_pidfile) as fp_:
nginx_pid = int(fp_.read().strip())
nginx_proc = psutil.Process(pid=nginx_pid)
self.addCleanup(nginx_proc.send_signal, signal.SIGQUIT)
for code in ('', '301', '302'):
url = url_prefix + (code or 'actual_file')
log.debug('attempting to cache %s', url)
ret = self.run_function('cp.cache_file', [url])
with salt.utils.fopen(ret) as fp_:
cached_contents = fp_.read()
self.assertEqual(cached_contents, file_contents)
def test_list_states(self):
'''
cp.list_states

View File

@ -22,6 +22,7 @@ def _find_new_locale(current_locale):
@skipIf(salt.utils.is_windows(), 'minion is windows')
@skipIf(salt.utils.is_darwin(), 'locale method is not supported on mac')
@requires_salt_modules('locale')
class LocaleModuleTest(ModuleCase):
def test_get_locale(self):

View File

@ -99,10 +99,13 @@ class ArchiveTest(ModuleCase, SaltReturnAssertsMixin):
'''
test archive.extracted with user and group set to "root"
'''
r_group = 'root'
if salt.utils.is_darwin():
r_group = 'wheel'
ret = self.run_state('archive.extracted', name=ARCHIVE_DIR,
source=self.archive_tar_source, archive_format='tar',
source_hash=ARCHIVE_TAR_HASH,
user='root', group='root')
user='root', group=r_group)
log.debug('ret = %s', ret)
if 'Timeout' in ret:
self.skipTest('Timeout talking to local tornado server.')

View File

@ -545,6 +545,9 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
'''
Test file.managed passing a basic check_cmd kwarg. See Issue #38111.
'''
r_group = 'root'
if salt.utils.is_darwin():
r_group = 'wheel'
if not salt.utils.which('visudo'):
self.fail('sudo is missing')
try:
@ -552,7 +555,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
'file.managed',
name='/tmp/sudoers',
user='root',
group='root',
group=r_group,
mode=440,
check_cmd='visudo -c -s -f'
)

View File

@ -104,7 +104,8 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('user.present', name=self.user_name,
home=self.user_home)
self.assertSaltTrueReturn(ret)
self.assertTrue(os.path.isdir(self.user_home))
if not salt.utils.is_darwin():
self.assertTrue(os.path.isdir(self.user_home))
@requires_system_grains
def test_user_present_gid_from_name_default(self, grains=None):
@ -127,7 +128,8 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin):
self.assertReturnNonEmptySaltType(ret)
group_name = grp.getgrgid(ret['gid']).gr_name
self.assertTrue(os.path.isdir(self.user_home))
if not salt.utils.is_darwin():
self.assertTrue(os.path.isdir(self.user_home))
if grains['os_family'] in ('Suse',):
self.assertEqual(group_name, 'users')
elif grains['os_family'] == 'MacOS':
@ -151,7 +153,8 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin):
self.assertReturnNonEmptySaltType(ret)
group_name = grp.getgrgid(ret['gid']).gr_name
self.assertTrue(os.path.isdir(self.user_home))
if not salt.utils.is_darwin():
self.assertTrue(os.path.isdir(self.user_home))
self.assertEqual(group_name, self.user_name)
ret = self.run_state('user.absent', name=self.user_name)
self.assertSaltTrueReturn(ret)

View File

@ -771,11 +771,11 @@ class TestDaemon(TestProgram):
if not self._shutdown:
try:
pid = self.wait_for_daemon_pid(timeout)
terminate_process(pid=pid)
terminate_process(pid=pid, kill_children=True)
except TimeoutError:
pass
if self.process:
terminate_process(pid=self.process.pid)
terminate_process(pid=self.process.pid, kill_children=True)
self.process.wait()
self.process = None
self._shutdown = True

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
'''
:copyright: © 2013-2017 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2013-2017 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -6,7 +6,7 @@
Salt Tests CLI access classes
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2013-2017 by the SaltStack Team, see AUTHORS for more details
:copyright: Copyright 2013-2017 by the SaltStack Team, see AUTHORS for more details
:license: Apache 2.0, see LICENSE for more details.
'''
# pylint: disable=repr-flag-used-in-string

View File

@ -6,7 +6,7 @@
Code coverage aware testing parser
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2013 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2013 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.
'''
# pylint: disable=repr-flag-used-in-string

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2017 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2017 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
'''
:copyright: © 2017 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2017 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2014 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2014 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2017 by the SaltStack Team, see AUTHORS for more details.
:copyright: Copyright 2017 by the SaltStack Team, see AUTHORS for more details.
tests.unit.beacons.test_status

View File

@ -314,7 +314,7 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
'keystone.endpoint_create': mock}):
comt = ('Endpoint for service "{0}" already exists'.format(name))
ret.update({'comment': comt, 'result': None, 'changes': {}})
ret.update({'comment': comt, 'result': True, 'changes': {}})
self.assertDictEqual(keystone.endpoint_present(name), ret)
with patch.dict(keystone.__opts__, {'test': True}):
@ -323,7 +323,7 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
self.assertDictEqual(keystone.endpoint_present(name), ret)
comt = ('Endpoint for service "{0}" already exists'.format(name))
ret.update({'comment': comt, 'result': None, 'changes': {}})
ret.update({'comment': comt, 'result': True, 'changes': {}})
self.assertDictEqual(keystone.endpoint_present(name), ret)
with patch.dict(keystone.__opts__, {'test': False}):