Merge branch 'develop' into lxc-consistency-fixes

This commit is contained in:
J. Eduardo 2017-07-31 22:06:56 +02:00 committed by GitHub
commit b46de3f976
22 changed files with 540 additions and 60 deletions

View File

@ -386,3 +386,24 @@ script, a cloud profile using ``file_map`` might look like:
file_map:
/local/path/to/custom/script: /remote/path/to/use/custom/script
/local/path/to/package: /remote/path/to/store/package
Running Pre-Flight Commands
===========================
.. versionadded:: Oxygen
To execute specified preflight shell commands on a VM before the deploy script is
run, use the ``preflight_cmds`` option. These must be defined as a list in a cloud
configuration file. For example:
.. code-block:: yaml
my-cloud-profile:
provider: linode-config
image: Ubuntu 16.04 LTS
size: Linode 2048
preflight_cmds:
- whoami
- echo 'hello world!'
These commands will run in sequence **before** the bootstrap script is executed.

View File

@ -25,6 +25,19 @@ by any master tops matches that are not matched via a top file.
To make master tops matches execute first, followed by top file matches, set
the new :conf_minion:`master_tops_first` minion config option to ``True``.
LDAP via External Authentication Changes
----------------------------------------
In this release of Salt, if LDAP Bind Credentials are supplied, then
these credentials will be used for all LDAP access except the first
authentication when a job is submitted. The first authentication will
use the user's credentials as passed on the CLI. This behavior is to
accommodate certain two-factor authentication schemes where the authentication
token can only be used once.
In previous releases the bind credentials would only be used to determine
the LDAP user's existence and group membership. The user's LDAP credentials
were used from then on.
New GitFS Features
------------------
@ -49,8 +62,30 @@ environments (i.e. ``saltenvs``) have been added:
ignore all tags and use branches only, and also to keep SHAs from being made
available as saltenvs.
Salt Cloud and Newer PyWinRM Versions
-------------------------------------
Salt Cloud Features
===================
Pre-Flight Commands
-------------------
Support has been added for specified "preflight commands" to run on a VM before
the deploy script is run. These must be defined as a list in a cloud configuration
file. For example:
.. code-block:: yaml
my-cloud-profile:
provider: linode-config
image: Ubuntu 16.04 LTS
size: Linode 2048
preflight_cmds:
- whoami
- echo 'hello world!'
These commands will run in sequence **before** the bootstrap script is executed.
Newer PyWinRM Versions
----------------------
Versions of ``pywinrm>=0.2.1`` are finally able to disable validation of self
signed certificates. :ref:`Here<new-pywinrm>` for more information.

View File

@ -280,8 +280,14 @@ def auth(username, password):
'''
Simple LDAP auth
'''
if _bind(username, password, anonymous=_config('auth_by_group_membership_only', mandatory=False) and
_config('anonymous', mandatory=False)):
#If bind credentials are configured, use them instead of user's
if _config('binddn', mandatory=False) and _config('bindpw', mandatory=False):
bind = _bind_for_search(anonymous=_config('anonymous', mandatory=False))
else:
bind = _bind(username, password, anonymous=_config('auth_by_group_membership_only', mandatory=False) and
_config('anonymous', mandatory=False))
if bind:
log.debug('LDAP authentication successful')
return True
else:
@ -306,8 +312,9 @@ def groups(username, **kwargs):
'''
group_list = []
bind = _bind(username, kwargs['password'],
anonymous=_config('anonymous', mandatory=False))
# Perform un-authenticated bind to determine group membership
bind = _bind_for_search(anonymous=_config('anonymous', mandatory=False))
if bind:
log.debug('ldap bind to determine group membership succeeded!')
@ -381,7 +388,11 @@ def groups(username, **kwargs):
group_list.append(group.split(',')[0].split('=')[-1])
log.debug('User {0} is a member of groups: {1}'.format(username, group_list))
if not auth(username, kwargs['password']):
# Only test user auth on first call for job.
# 'show_jid' only exists on first payload so we can use that for the conditional.
if 'show_jid' in kwargs and not _bind(username, kwargs['password'],
anonymous=_config('auth_by_group_membership_only', mandatory=False) and
_config('anonymous', mandatory=False)):
log.error('LDAP username and password do not match')
return []
else:

View File

@ -1305,10 +1305,8 @@ class AESFuncs(object):
with salt.utils.files.fopen(cpath, mode) as fp_:
if load['loc']:
fp_.seek(load['loc'])
if six.PY3:
fp_.write(load['data'].encode(__salt_system_encoding__))
else:
fp_.write(load['data'])
fp_.write(load['data'])
return True
def _pillar(self, load):

View File

@ -770,6 +770,7 @@ def run(cmd,
bg=False,
password=None,
encoded_cmd=False,
raise_err=False,
**kwargs):
r'''
Execute the passed command and return the output as a string
@ -873,6 +874,10 @@ def run(cmd,
:param bool encoded_cmd: Specify if the supplied command is encoded.
Only applies to shell 'powershell'.
:param bool raise_err: Specifies whether to raise a CommandExecutionError.
If False, the error will be logged, but no exception will be raised.
Default is False.
.. warning::
This function does not process commands through a shell
unless the python_shell flag is set to True. This means that any
@ -962,6 +967,8 @@ def run(cmd,
)
)
log.error(log_callback(msg))
if raise_err:
raise CommandExecutionError(log_callback(ret['stdout']))
log.log(lvl, 'output: {0}'.format(log_callback(ret['stdout'])))
return ret['stdout']

View File

@ -213,8 +213,10 @@ def modfacl(acl_type, acl_name='', perms='', *args, **kwargs):
salt '*' acl.modfacl d:u myuser 7 /tmp/house/kitchen
salt '*' acl.modfacl g mygroup 0 /tmp/house/kitchen /tmp/house/livingroom
salt '*' acl.modfacl user myuser rwx /tmp/house/kitchen recursive=True
salt '*' acl.modfacl user myuser rwx /tmp/house/kitchen raise_err=True
'''
recursive = kwargs.pop('recursive', False)
raise_err = kwargs.pop('raise_err', False)
_raise_on_no_files(*args)
@ -228,7 +230,7 @@ def modfacl(acl_type, acl_name='', perms='', *args, **kwargs):
for dentry in args:
cmd += ' "{0}"'.format(dentry)
__salt__['cmd.run'](cmd, python_shell=False)
__salt__['cmd.run'](cmd, python_shell=False, raise_err=raise_err)
return True

View File

@ -27,7 +27,7 @@ def __virtual__():
'''
Set the virtual pkg module if the os is Solaris
'''
if __grains__['os'] == 'Solaris':
if __grains__['os_family'] == 'Solaris':
return __virtualname__
return (False, 'The pkgutil execution module cannot be loaded: '
'only available on Solaris systems.')

View File

@ -56,7 +56,7 @@ def __virtual__():
'''
Set the virtual pkg module if the os is Solaris 11
'''
if __grains__['os'] == 'Solaris' \
if __grains__['os_family'] == 'Solaris' \
and float(__grains__['kernelrelease']) > 5.10 \
and salt.utils.which('pkg'):
return __virtualname__

View File

@ -30,7 +30,7 @@ def __virtual__():
'''
Set the virtual pkg module if the os is Solaris
'''
if __grains__['os'] == 'Solaris' and float(__grains__['kernelrelease']) <= 5.10:
if __grains__['os_family'] == 'Solaris' and float(__grains__['kernelrelease']) <= 5.10:
return __virtualname__
return (False,
'The solarispkg execution module failed to load: only available '

View File

@ -61,11 +61,11 @@ def __virtual__():
We are available if we are have zoneadm and are the global zone on
Solaris 10, OmniOS, OpenIndiana, OpenSolaris, or Smartos.
'''
## note: we depend on PR#37472 to distinguish between Solaris and Oracle Solaris
if _is_globalzone() and salt.utils.which('zoneadm'):
if __grains__['os'] in ['Solaris', 'OpenSolaris', 'SmartOS', 'OmniOS', 'OpenIndiana']:
if __grains__['os'] in ['OpenSolaris', 'SmartOS', 'OmniOS', 'OpenIndiana']:
return __virtualname__
elif __grains__['os'] == 'Oracle Solaris' and int(__grains__['osmajorrelease']) == 10:
return __virtualname__
return (
False,
'{0} module can only be loaded in a solaris globalzone.'.format(

View File

@ -97,11 +97,11 @@ def __virtual__():
We are available if we are have zonecfg and are the global zone on
Solaris 10, OmniOS, OpenIndiana, OpenSolaris, or Smartos.
'''
# note: we depend on PR#37472 to distinguish between Solaris and Oracle Solaris
if _is_globalzone() and salt.utils.which('zonecfg'):
if __grains__['os'] in ['Solaris', 'OpenSolaris', 'SmartOS', 'OmniOS', 'OpenIndiana']:
if __grains__['os'] in ['OpenSolaris', 'SmartOS', 'OmniOS', 'OpenIndiana']:
return __virtualname__
elif __grains__['os'] == 'Oracle Solaris' and int(__grains__['osmajorrelease']) == 10:
return __virtualname__
return (
False,
'{0} module can only be loaded in a solaris globalzone.'.format(

View File

@ -34,6 +34,9 @@ import os
# Import salt libs
import salt.utils
# Impot salt exceptions
from salt.exceptions import CommandExecutionError
# Import 3rd-party libs
import salt.ext.six as six
@ -57,6 +60,7 @@ def present(name, acl_type, acl_name='', perms='', recurse=False):
ret = {'name': name,
'result': True,
'changes': {},
'pchanges': {},
'comment': ''}
_octal = {'r': 4, 'w': 2, 'x': 1, '-': 0}
@ -99,21 +103,54 @@ def present(name, acl_type, acl_name='', perms='', recurse=False):
if user[_search_name]['octal'] == sum([_octal.get(i, i) for i in perms]):
ret['comment'] = 'Permissions are in the desired state'
else:
ret['comment'] = 'Permissions have been updated'
changes = {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms},
'old': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': str(user[_search_name]['octal'])}}
if __opts__['test']:
ret['result'] = None
ret.update({'comment': 'Updated permissions will be applied for '
'{0}: {1} -> {2}'.format(
acl_name,
str(user[_search_name]['octal']),
perms),
'result': None, 'pchanges': changes})
return ret
__salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse)
try:
__salt__['acl.modfacl'](acl_type, acl_name, perms, name,
recursive=recurse, raise_err=True)
ret.update({'comment': 'Updated permissions for '
'{0}'.format(acl_name),
'result': True, 'changes': changes})
except CommandExecutionError as exc:
ret.update({'comment': 'Error updating permissions for '
'{0}: {1}'.format(acl_name, exc.strerror),
'result': False})
else:
ret['comment'] = 'Permissions will be applied'
changes = {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms}}
if __opts__['test']:
ret.update({'comment': 'New permissions will be applied for '
'{0}: {1}'.format(acl_name, perms),
'result': None, 'pchanges': changes})
ret['result'] = None
return ret
__salt__['acl.modfacl'](acl_type, acl_name, perms, name, recursive=recurse)
try:
__salt__['acl.modfacl'](acl_type, acl_name, perms, name,
recursive=recurse, raise_err=True)
ret.update({'comment': 'Applied new permissions for '
'{0}'.format(acl_name),
'result': True, 'changes': changes})
except CommandExecutionError as exc:
ret.update({'comment': 'Error updating permissions for {0}: '
'{1}'.format(acl_name, exc.strerror),
'result': False})
else:
ret['comment'] = 'ACL Type does not exist'
ret['result'] = False

View File

@ -452,6 +452,9 @@ def bootstrap(vm_, opts):
'maxtries': salt.config.get_cloud_config_value(
'wait_for_passwd_maxtries', vm_, opts, default=15
),
'preflight_cmds': salt.config.get_cloud_config_value(
'preflight_cmds', vm_, __opts__, default=[]
),
}
inline_script_kwargs = deploy_kwargs
@ -1465,6 +1468,15 @@ def deploy_script(host,
'Can\'t set ownership for {0}'.format(
preseed_minion_keys_tempdir))
# Run any pre-flight commands before running deploy scripts
preflight_cmds = kwargs.get('preflight_cmds', [])
for command in preflight_cmds:
cmd_ret = root_cmd(command, tty, sudo, **ssh_kwargs)
if cmd_ret:
raise SaltCloudSystemExit(
'Pre-flight command failed: \'{0}\''.format(command)
)
# The actual deploy script
if script:
# got strange escaping issues with sudoer, going onto a

View File

@ -242,8 +242,8 @@ def _get_service_instance(host, username, password, protocol,
b64token=token,
mechanism=mechanism)
else:
log.exception(exc)
err_msg = exc.msg if hasattr(exc, 'msg') else default_msg
log.trace(exc)
raise salt.exceptions.VMwareConnectionError(err_msg)
except Exception as exc:
if 'certificate verify failed' in str(exc):
@ -262,8 +262,8 @@ def _get_service_instance(host, username, password, protocol,
mechanism=mechanism
)
except Exception as exc:
log.exception(exc)
err_msg = exc.msg if hasattr(exc, 'msg') else str(exc)
log.trace(err_msg)
raise salt.exceptions.VMwareConnectionError(
'Could not connect to host \'{0}\': '
'{1}'.format(host, err_msg))
@ -388,9 +388,16 @@ def get_service_instance(host, username=None, password=None, protocol=None,
mechanism,
principal,
domain)
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
return service_instance
@ -425,9 +432,16 @@ def disconnect(service_instance):
log.trace('Disconnecting')
try:
Disconnect(service_instance)
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
@ -441,9 +455,16 @@ def is_connection_to_a_vcenter(service_instance):
'''
try:
api_type = service_instance.content.about.apiType
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
log.trace('api_type = {0}'.format(api_type))
if api_type == 'VirtualCenter':
@ -648,9 +669,16 @@ def get_root_folder(service_instance):
try:
log.trace('Retrieving root folder')
return service_instance.RetrieveContent().rootFolder
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
@ -700,9 +728,16 @@ def get_content(service_instance, obj_type, property_list=None,
try:
obj_ref = service_instance.content.viewManager.CreateContainerView(
container_ref, [obj_type], True)
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
# Create 'Traverse All' traversal spec to determine the path for
@ -738,18 +773,32 @@ def get_content(service_instance, obj_type, property_list=None,
# Retrieve the contents
try:
content = service_instance.content.propertyCollector.RetrieveContents([filter_spec])
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
# Destroy the object view
if local_traversal_spec:
try:
obj_ref.Destroy()
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
return content
@ -1000,9 +1049,16 @@ def create_datacenter(service_instance, datacenter_name):
log.trace('Creating datacenter \'{0}\''.format(datacenter_name))
try:
dc_obj = root_folder.CreateDatacenter(datacenter_name)
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
return dc_obj
@ -1062,9 +1118,16 @@ def create_cluster(dc_ref, cluster_name, cluster_spec):
''.format(cluster_name, dc_name))
try:
dc_ref.hostFolder.CreateClusterEx(cluster_name, cluster_spec)
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
@ -1084,9 +1147,16 @@ def update_cluster(cluster_ref, cluster_spec):
try:
task = cluster_ref.ReconfigureComputeResource_Task(cluster_spec,
modify=True)
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
wait_for_task(task, cluster_name, 'ClusterUpdateTask')
@ -1291,9 +1361,16 @@ def wait_for_task(task, instance_name, task_type, sleep_seconds=1, log_level='de
task.__class__.__name__))
try:
task_info = task.info
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
while task_info.state == 'running' or task_info.state == 'queued':
if time_counter % sleep_seconds == 0:
@ -1307,9 +1384,16 @@ def wait_for_task(task, instance_name, task_type, sleep_seconds=1, log_level='de
time_counter += 1
try:
task_info = task.info
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.RuntimeFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareRuntimeError(exc.msg)
if task_info.state == 'success':
msg = '[ {0} ] Successfully completed {1} task in {2} seconds'.format(
@ -1324,11 +1408,19 @@ def wait_for_task(task, instance_name, task_type, sleep_seconds=1, log_level='de
# task is in an error state
try:
raise task_info.error
except vim.fault.NoPermission as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(
'Not enough permissions. Required privilege: '
'{}'.format(exc.privilegeId))
except vim.fault.VimFault as exc:
log.exception(exc)
raise salt.exceptions.VMwareApiError(exc.msg)
except vmodl.fault.SystemError as exc:
log.exception(exc)
raise salt.exceptions.VMwareSystemError(exc.msg)
except vmodl.fault.InvalidArgument as exc:
log.exception(exc)
exc_message = exc.msg
if exc.faultMessage:
exc_message = '{0} ({1})'.format(exc_message,

View File

@ -6,7 +6,7 @@ from __future__ import absolute_import
# Import Salt Testing libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import skipIf, TestCase
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
# Import salt libs
import salt.modules.linux_acl as linux_acl
@ -84,63 +84,70 @@ class LinuxAclTestCase(TestCase, LoaderModuleMockMixin):
def test_modfacl__u_w_single_arg(self):
linux_acl.modfacl(*(self.u_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__u_w_multiple_args(self):
linux_acl.modfacl(*(self.u_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__user_w_single_arg(self):
linux_acl.modfacl(*(self.user_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__user_w_multiple_args(self):
linux_acl.modfacl(*(self.user_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.user_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__g_w_single_arg(self):
linux_acl.modfacl(*(self.g_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__g_w_multiple_args(self):
linux_acl.modfacl(*(self.g_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__group_w_single_arg(self):
linux_acl.modfacl(*(self.group_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__group_w_multiple_args(self):
linux_acl.modfacl(*(self.group_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.group_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__d_u_w_single_arg(self):
linux_acl.modfacl(*(self.d_u_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__d_u_w_multiple_args(self):
linux_acl.modfacl(*(self.d_u_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__d_user_w_single_arg(self):
linux_acl.modfacl(*(self.d_user_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__d_user_w_multiple_args(self):
linux_acl.modfacl(*(self.d_user_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__default_user_w_single_arg(self):
linux_acl.modfacl(*(self.default_user_acl + [self.file]))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd, self.quoted_file]), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd, self.quoted_file]), python_shell=False, raise_err=False)
def test_modfacl__default_user_w_multiple_args(self):
linux_acl.modfacl(*(self.default_user_acl + self.files))
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -m ' + ' '.join([self.default_user_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl__recursive_w_multiple_args(self):
linux_acl.modfacl(*(self.user_acl + self.files), recursive=True)
self.cmdrun.assert_called_once_with('setfacl -R -m ' + ' '.join([self.user_acl_cmd] + self.quoted_files), python_shell=False)
self.cmdrun.assert_called_once_with('setfacl -R -m ' + ' '.join([self.user_acl_cmd] + self.quoted_files), python_shell=False, raise_err=False)
def test_modfacl_raise_err(self):
mock = MagicMock(side_effect=CommandExecutionError('Custom err'))
with patch.dict(linux_acl.__salt__, {'cmd.run': mock}):
with self.assertRaises(CommandExecutionError) as excinfo:
linux_acl.modfacl(*(self.user_acl + self.files), raise_err=True)
self.assertEqual(excinfo.exception.strerror, 'Custom err')
def test_delfacl_wo_args(self):
for acl in [self.u_acl, self.user_acl, self.g_acl, self.group_acl]:

View File

@ -15,8 +15,10 @@ from tests.support.mock import (
MagicMock,
patch)
# Import Salt Libs
import salt.states.linux_acl as linux_acl
from salt.exceptions import CommandExecutionError
@skipIf(NO_MOCK, NO_MOCK_REASON)
@ -34,34 +36,120 @@ class LinuxAclTestCase(TestCase, LoaderModuleMockMixin):
'''
Test to ensure a Linux ACL is present
'''
self.maxDiff = None
name = '/root'
acl_type = 'users'
acl_name = 'damian'
perms = 'rwx'
ret = {'name': name,
'result': None,
'comment': '',
'changes': {}}
mock = MagicMock(side_effect=[{name: {acl_type: [{acl_name:
{'octal': 'A'}}]}},
{'octal': 'A'}}]}},
{name: {acl_type: [{acl_name:
{'octal': 'A'}}]}},
{name: {acl_type: [{acl_name:
{'octal': 'A'}}]}},
{name: {acl_type: [{}]}},
{name: {acl_type: [{}]}},
{name: {acl_type: [{}]}},
{name: {acl_type: ''}}])
mock_modfacl = MagicMock(return_value=True)
with patch.dict(linux_acl.__salt__, {'acl.getfacl': mock}):
# Update - test=True
with patch.dict(linux_acl.__opts__, {'test': True}):
comt = ('Permissions have been updated')
ret.update({'comment': comt})
comt = ('Updated permissions will be applied for {0}: A -> {1}'
''.format(acl_name, perms))
ret = {'name': name,
'comment': comt,
'changes': {},
'pchanges': {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms},
'old': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': 'A'}},
'result': None}
self.assertDictEqual(linux_acl.present(name, acl_type, acl_name,
perms), ret)
comt = ('Permissions will be applied')
ret.update({'comment': comt})
self.assertDictEqual(linux_acl.present(name, acl_type, acl_name,
perms), ret)
# Update - test=False
with patch.dict(linux_acl.__salt__, {'acl.modfacl': mock_modfacl}):
with patch.dict(linux_acl.__opts__, {'test': False}):
comt = ('Updated permissions for {0}'.format(acl_name))
ret = {'name': name,
'comment': comt,
'changes': {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms},
'old': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': 'A'}},
'pchanges': {},
'result': True}
self.assertDictEqual(linux_acl.present(name, acl_type,
acl_name, perms),
ret)
# Update - modfacl error
with patch.dict(linux_acl.__salt__, {'acl.modfacl': MagicMock(
side_effect=CommandExecutionError('Custom err'))}):
with patch.dict(linux_acl.__opts__, {'test': False}):
comt = ('Error updating permissions for {0}: Custom err'
''.format(acl_name))
ret = {'name': name,
'comment': comt,
'changes': {},
'pchanges': {},
'result': False}
self.assertDictEqual(linux_acl.present(name, acl_type,
acl_name, perms),
ret)
# New - test=True
with patch.dict(linux_acl.__salt__, {'acl.modfacl': mock_modfacl}):
with patch.dict(linux_acl.__opts__, {'test': True}):
comt = ('New permissions will be applied '
'for {0}: {1}'.format(acl_name, perms))
ret = {'name': name,
'comment': comt,
'changes': {},
'pchanges': {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms}},
'result': None}
self.assertDictEqual(linux_acl.present(name, acl_type,
acl_name, perms),
ret)
# New - test=False
with patch.dict(linux_acl.__salt__, {'acl.modfacl': mock_modfacl}):
with patch.dict(linux_acl.__opts__, {'test': False}):
comt = ('Applied new permissions for {0}'.format(acl_name))
ret = {'name': name,
'comment': comt,
'changes': {'new': {'acl_name': acl_name,
'acl_type': acl_type,
'perms': perms}},
'pchanges': {},
'result': True}
self.assertDictEqual(linux_acl.present(name, acl_type,
acl_name, perms),
ret)
# New - modfacl error
with patch.dict(linux_acl.__salt__, {'acl.modfacl': MagicMock(
side_effect=CommandExecutionError('Custom err'))}):
with patch.dict(linux_acl.__opts__, {'test': False}):
comt = ('Error updating permissions for {0}: Custom err'
''.format(acl_name))
ret = {'name': name,
'comment': comt,
'changes': {},
'pchanges': {},
'result': False}
self.assertDictEqual(linux_acl.present(name, acl_type,
acl_name, perms),
ret)
# No acl type
comt = ('ACL Type does not exist')
ret.update({'comment': comt, 'result': False})
ret = {'name': name, 'comment': comt, 'result': False,
'changes': {}, 'pchanges': {}}
self.assertDictEqual(linux_acl.present(name, acl_type, acl_name,
perms), ret)

View File

@ -178,6 +178,18 @@ class CreateClusterTestCase(TestCase):
self.mock_create_cluster_ex.assert_called_once_with(
'fake_cluster', self.mock_cluster_spec)
def test_create_cluster_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
self.mock_dc.hostFolder.CreateClusterEx = MagicMock(
side_effect=exc)
with self.assertRaises(VMwareApiError) as excinfo:
vmware.create_cluster(self.mock_dc, 'fake_cluster',
self.mock_cluster_spec)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_create_cluster_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -234,6 +246,17 @@ class UpdateClusterTestCase(TestCase):
self.mock_reconfigure_compute_resource_task.assert_called_once_with(
self.mock_cluster_spec, modify=True)
def test_reconfigure_compute_resource_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
self.mock_cluster.ReconfigureComputeResource_Task = \
MagicMock(side_effect=exc)
with self.assertRaises(VMwareApiError) as excinfo:
vmware.update_cluster(self.mock_cluster, self.mock_cluster_spec)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_reconfigure_compute_resource_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'

View File

@ -43,6 +43,19 @@ class WaitForTaskTestCase(TestCase):
patcher.start()
self.addCleanup(patcher.stop)
def test_first_task_info_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
mock_task = MagicMock()
type(mock_task).info = PropertyMock(side_effect=exc)
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.wait_for_task(mock_task,
'fake_instance_name',
'task_type')
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_first_task_info_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -65,6 +78,22 @@ class WaitForTaskTestCase(TestCase):
'task_type')
self.assertEqual(excinfo.exception.strerror, 'RuntimeFault msg')
def test_inner_loop_task_info_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
mock_task = MagicMock()
mock_info1 = MagicMock()
type(mock_task).info = PropertyMock(
side_effect=[mock_info1, exc])
type(mock_info1).state = PropertyMock(side_effect=['running', 'bad'])
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.wait_for_task(mock_task,
'fake_instance_name',
'task_type')
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_inner_loop_task_info_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -161,6 +190,22 @@ class WaitForTaskTestCase(TestCase):
'task_type')
self.assertEqual(str(excinfo.exception), 'error exc')
def test_info_error_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
mock_task = MagicMock()
prop_mock_state = PropertyMock(return_value='error')
prop_mock_error = PropertyMock(side_effect=exc)
type(mock_task.info).state = prop_mock_state
type(mock_task.info).error = prop_mock_error
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.wait_for_task(mock_task,
'fake_instance_name',
'task_type')
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_info_error_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -658,6 +703,19 @@ class GetContentTestCase(TestCase):
# check destroy is called
self.assertEqual(self.destroy_mock.call_count, 1)
def test_create_container_view_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
self.si_mock.content.viewManager.CreateContainerView = \
MagicMock(side_effect=exc)
with patch('salt.utils.vmware.get_root_folder',
self.get_root_folder_mock):
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.get_content(self.si_mock, self.obj_type_mock)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_create_container_view_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -680,6 +738,19 @@ class GetContentTestCase(TestCase):
salt.utils.vmware.get_content(self.si_mock, self.obj_type_mock)
self.assertEqual(excinfo.exception.strerror, 'RuntimeFault msg')
def test_destroy_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
self.si_mock.content.viewManager.CreateContainerView = MagicMock(
return_value=MagicMock(Destroy=MagicMock(side_effect=exc)))
with patch('salt.utils.vmware.get_root_folder',
self.get_root_folder_mock):
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.get_content(self.si_mock, self.obj_type_mock)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_destroy_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -745,6 +816,17 @@ class GetContentTestCase(TestCase):
[self.filter_spec_ret_mock])
self.assertEqual(ret, self.result_mock)
def test_retrieve_contents_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
self.si_mock.content.propertyCollector.RetrieveContents = \
MagicMock(side_effect=exc)
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.get_content(self.si_mock, self.obj_type_mock)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_retrieve_contents_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -789,6 +871,16 @@ class GetRootFolderTestCase(TestCase):
self.mock_si = MagicMock(
RetrieveContent=MagicMock(return_value=self.mock_content))
def test_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
type(self.mock_content).rootFolder = PropertyMock(side_effect=exc)
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.get_root_folder(self.mock_si)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'

View File

@ -688,6 +688,26 @@ class GetServiceInstanceTestCase(TestCase):
self.assertEqual(mock_disconnect.call_count, 1)
self.assertEqual(mock_get_si.call_count, 2)
def test_current_time_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
with patch('salt.utils.vmware._get_service_instance',
MagicMock(return_value=MagicMock(
CurrentTime=MagicMock(side_effect=exc)))):
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.get_service_instance(
host='fake_host',
username='fake_username',
password='fake_password',
protocol='fake_protocol',
port=1,
mechanism='fake_mechanism',
principal='fake_principal',
domain='fake_domain')
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_current_time_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -741,6 +761,17 @@ class DisconnectTestCase(TestCase):
service_instance=self.mock_si)
mock_disconnect.assert_called_once_with(self.mock_si)
def test_disconnect_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
with patch('salt.utils.vmware.Disconnect', MagicMock(side_effect=exc)):
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.disconnect(
service_instance=self.mock_si)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_disconnect_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'
@ -765,6 +796,17 @@ class DisconnectTestCase(TestCase):
class IsConnectionToAVCenterTestCase(TestCase):
'''Tests for salt.utils.vmware.is_connection_to_a_vcenter'''
def test_api_type_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
mock_si = MagicMock()
type(mock_si.content.about).apiType = PropertyMock(side_effect=exc)
with self.assertRaises(excs.VMwareApiError) as excinfo:
salt.utils.vmware.is_connection_to_a_vcenter(mock_si)
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_api_type_raise_vim_fault(self):
exc = vim.fault.VimFault()
exc.msg = 'VimFault msg'

View File

@ -164,6 +164,19 @@ class CreateDatacenterTestCase(TestCase):
vmware.create_datacenter(self.mock_si, 'fake_dc')
self.mock_create_datacenter.assert_called_once_with('fake_dc')
def test_create_datacenter_raise_no_permission(self):
exc = vim.fault.NoPermission()
exc.privilegeId = 'Fake privilege'
self.mock_root_folder = MagicMock(
CreateDatacenter=MagicMock(side_effect=exc))
with patch('salt.utils.vmware.get_root_folder',
MagicMock(return_value=self.mock_root_folder)):
with self.assertRaises(VMwareApiError) as excinfo:
vmware.create_datacenter(self.mock_si, 'fake_dc')
self.assertEqual(excinfo.exception.strerror,
'Not enough permissions. Required privilege: '
'Fake privilege')
def test_create_datacenter_raise_vim_fault(self):
exc = vim.VimFault()
exc.msg = 'VimFault msg'