mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #34025 from rallytime/merge-2016.3
[2016.3] Merge forward from 2015.8 to 2016.3
This commit is contained in:
parent
3035520594
commit
f546a00dc9
24 changed files with 470 additions and 160 deletions
|
@ -1,15 +0,0 @@
|
|||
Community Projects That Use Salt
|
||||
================================
|
||||
|
||||
Below is a list of repositories that show real world Salt applications that
|
||||
you can use to get started. Please note that these projects do not adhere to
|
||||
any standards and express a wide variety of ideas and opinions on how an
|
||||
action can be completed with Salt.
|
||||
|
||||
https://github.com/terminalmage/djangocon2013-sls
|
||||
|
||||
https://github.com/jesusaurus/hpcs-salt-state
|
||||
|
||||
https://github.com/gravyboat/hungryadmin-sls
|
||||
|
||||
https://github.com/wunki/django-salted
|
|
@ -176,3 +176,14 @@ a security vulnerability.
|
|||
|
||||
:doc:`Installing Salt for development </topics/development/hacking>` and
|
||||
contributing to the project.
|
||||
|
||||
Building Packages using Salt Pack
|
||||
---------------------------------
|
||||
|
||||
Salt-pack is an open-source package builder for most commonly used Linux
|
||||
platforms, for example: Redhat/CentOS and Debian/Ubuntu families, utilizing
|
||||
SaltStack states and execution modules to build Salt and a specified set of
|
||||
dependencies, from which a platform specific repository can be built.
|
||||
|
||||
https://github.com/saltstack/salt-pack
|
||||
|
||||
|
|
|
@ -1,29 +1,47 @@
|
|||
===================
|
||||
Salt Based Projects
|
||||
===================
|
||||
=======================
|
||||
Salt Community Projects
|
||||
=======================
|
||||
|
||||
A number of unofficial open source projects, based on Salt, or written to
|
||||
enhance Salt have been created.
|
||||
This page contains links to Salt-related projects created by community members.
|
||||
If you come across a useful project please add it to the list!
|
||||
|
||||
Hubblestack
|
||||
===========
|
||||
Hubble is a modular, open-source security compliance framework built on top of
|
||||
SaltStack. The project provides on-demand profile-based auditing, real-time
|
||||
security event notifications, automated remediation, alerting and reporting.
|
||||
|
||||
http://hubblestack.io/
|
||||
|
||||
alkali
|
||||
======
|
||||
alkali is a collections of SaltStack states and pillar data that provide just
|
||||
the basics for provisioning Linux instances that may be built upon. alkali is
|
||||
a starter kit of sorts, to help new users to SaltStack get up-and-running
|
||||
quickly with the most commonly used, core packages.
|
||||
|
||||
https://github.com/zulily/alkali
|
||||
|
||||
buoyant
|
||||
=======
|
||||
buoyant leverages docker to provide an alternative to VM-centric SaltStack
|
||||
development environments. buoyant containers may be spun up nearly instantly,
|
||||
once an initial docker image has been built.
|
||||
|
||||
https://github.com/zulily/buoyant
|
||||
|
||||
Salt Sandbox
|
||||
============
|
||||
|
||||
Created by Aaron Bull Schaefer, aka "elasticdog".
|
||||
|
||||
https://github.com/elasticdog/salt-sandbox
|
||||
|
||||
Salt Sandbox is a multi-VM Vagrant-based Salt development environment used
|
||||
for creating and testing new Salt state modules outside of your production
|
||||
environment. It's also a great way to learn firsthand about Salt and its
|
||||
remote execution capabilities.
|
||||
|
||||
Salt Sandbox will set up three separate virtual machines:
|
||||
https://github.com/elasticdog/salt-sandbox
|
||||
|
||||
- salt.example.com - the Salt master server
|
||||
- minion1.example.com - the first Salt minion machine
|
||||
- minion2.example.com - the second Salt minion machine
|
||||
Salt Vagrant Demo
|
||||
=================
|
||||
A Salt Demo using Vagrant.
|
||||
|
||||
https://github.com/UtahDave/salt-vagrant-demo
|
||||
|
||||
These VMs can be used in conjunction to segregate and test your modules based
|
||||
on node groups, top file environments, grain values, etc. You can even test
|
||||
modules on different Linux distributions or release versions to better match
|
||||
your production infrastructure.
|
|
@ -201,7 +201,8 @@ def minion_mods(
|
|||
__opts__ = salt.config.minion_config('/etc/salt/minion')
|
||||
__grains__ = salt.loader.grains(__opts__)
|
||||
__opts__['grains'] = __grains__
|
||||
__salt__ = salt.loader.minion_mods(__opts__)
|
||||
__utils__ = salt.loader.utils(__opts__)
|
||||
__salt__ = salt.loader.minion_mods(__opts__, utils=__utils__)
|
||||
__salt__['test.ping']()
|
||||
'''
|
||||
# TODO Publish documentation for module whitelisting
|
||||
|
|
|
@ -1207,7 +1207,7 @@ def list_pkgs(versions_as_list=False,
|
|||
return ret
|
||||
|
||||
|
||||
def _get_upgradable(dist_upgrade=True):
|
||||
def _get_upgradable(dist_upgrade=True, **kwargs):
|
||||
'''
|
||||
Utility function to get upgradable packages
|
||||
|
||||
|
@ -1220,17 +1220,21 @@ def _get_upgradable(dist_upgrade=True):
|
|||
cmd.append('dist-upgrade')
|
||||
else:
|
||||
cmd.append('upgrade')
|
||||
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace', python_shell=False)
|
||||
fromrepo = _get_repo(**kwargs)
|
||||
if fromrepo:
|
||||
cmd.extend(['-o', 'APT::Default-Release={0}'.format(fromrepo)])
|
||||
|
||||
call = __salt__['cmd.run_all'](cmd,
|
||||
python_shell=False,
|
||||
output_loglevel='trace')
|
||||
|
||||
if call['retcode'] != 0:
|
||||
comment = ''
|
||||
if 'stderr' in call:
|
||||
comment += call['stderr']
|
||||
if 'stdout' in call:
|
||||
comment += call['stdout']
|
||||
raise CommandExecutionError(
|
||||
'{0}'.format(comment)
|
||||
)
|
||||
msg = 'Failed to get upgrades'
|
||||
for key in ('stderr', 'stdout'):
|
||||
if call[key]:
|
||||
msg += ': ' + call[key]
|
||||
break
|
||||
raise CommandExecutionError(msg)
|
||||
else:
|
||||
out = call['stdout']
|
||||
|
||||
|
@ -1253,7 +1257,7 @@ def _get_upgradable(dist_upgrade=True):
|
|||
return ret
|
||||
|
||||
|
||||
def list_upgrades(refresh=True, dist_upgrade=True):
|
||||
def list_upgrades(refresh=True, dist_upgrade=True, **kwargs):
|
||||
'''
|
||||
List all available package upgrades.
|
||||
|
||||
|
@ -1273,7 +1277,7 @@ def list_upgrades(refresh=True, dist_upgrade=True):
|
|||
'''
|
||||
if salt.utils.is_true(refresh):
|
||||
refresh_db()
|
||||
return _get_upgradable(dist_upgrade)
|
||||
return _get_upgradable(dist_upgrade, **kwargs)
|
||||
|
||||
|
||||
def upgrade_available(name):
|
||||
|
|
|
@ -266,14 +266,12 @@ def _get_upgradable(backtrack=3):
|
|||
python_shell=False)
|
||||
|
||||
if call['retcode'] != 0:
|
||||
comment = ''
|
||||
if 'stderr' in call:
|
||||
comment += call['stderr']
|
||||
if 'stdout' in call:
|
||||
comment += call['stdout']
|
||||
raise CommandExecutionError(
|
||||
'{0}'.format(comment)
|
||||
)
|
||||
msg = 'Failed to get upgrades'
|
||||
for key in ('stderr', 'stdout'):
|
||||
if call[key]:
|
||||
msg += ': ' + call[key]
|
||||
break
|
||||
raise CommandExecutionError(msg)
|
||||
else:
|
||||
out = call['stdout']
|
||||
|
||||
|
@ -296,7 +294,7 @@ def _get_upgradable(backtrack=3):
|
|||
return ret
|
||||
|
||||
|
||||
def list_upgrades(refresh=True, backtrack=3):
|
||||
def list_upgrades(refresh=True, backtrack=3, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
List all available package upgrades.
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@ def install(name=None, pkgs=None, taps=None, options=None, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def list_upgrades(refresh=True):
|
||||
def list_upgrades(refresh=True, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
Check whether or not an upgrade is available for all packages
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def list_upgrades(refresh=True):
|
||||
def list_upgrades(refresh=True, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
Check whether or not an upgrade is available for all packages
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ def upgrade_available(name):
|
|||
return latest_version(name) != ''
|
||||
|
||||
|
||||
def list_upgrades(refresh=False, root=None):
|
||||
def list_upgrades(refresh=False, root=None, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
List all available package upgrades on this system
|
||||
|
||||
|
@ -146,8 +146,8 @@ def list_upgrades(refresh=False, root=None):
|
|||
cmd.append('-y')
|
||||
|
||||
call = __salt__['cmd.run_all'](cmd,
|
||||
output_loglevel='trace',
|
||||
python_shell=False)
|
||||
python_shell=False,
|
||||
output_loglevel='trace')
|
||||
|
||||
if call['retcode'] != 0:
|
||||
comment = ''
|
||||
|
|
|
@ -6,22 +6,22 @@ from __future__ import absolute_import
|
|||
|
||||
# Import python libs
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Define the module's virtual name
|
||||
__virtualname__ = 'pam'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load the module if pam is installed
|
||||
Set the virtual name for the module
|
||||
'''
|
||||
if os.path.exists('/usr/lib/libpam.so'):
|
||||
return __virtualname__
|
||||
return (False, 'The pam execution module failed to load: '
|
||||
'pam is not installed.')
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _parse(contents=None, file_name=None):
|
||||
|
@ -34,6 +34,7 @@ def _parse(contents=None, file_name=None):
|
|||
with salt.utils.fopen(file_name, 'r') as ifile:
|
||||
contents = ifile.read()
|
||||
else:
|
||||
log.error('File "{0}" does not exist'.format(file_name))
|
||||
return False
|
||||
|
||||
rules = []
|
||||
|
|
|
@ -69,7 +69,7 @@ def upgrade_available(name):
|
|||
return ''
|
||||
|
||||
|
||||
def list_upgrades(refresh=True):
|
||||
def list_upgrades(refresh=True, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
List all available package upgrades on this system
|
||||
|
||||
|
|
|
@ -146,16 +146,19 @@ def upgrade_available(name):
|
|||
return ret
|
||||
|
||||
|
||||
def list_upgrades(refresh=False):
|
||||
def list_upgrades(refresh=False, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
Lists all packages available for update.
|
||||
When run in global zone, it reports only upgradable packages for the global zone.
|
||||
|
||||
When run in global zone, it reports only upgradable packages for the global
|
||||
zone.
|
||||
|
||||
When run in non-global zone, it can report more upgradable packages than
|
||||
"pkg update -vn" because "pkg update" hides packages that require newer
|
||||
version of pkg://solaris/entire (which means that they can be upgraded only
|
||||
from global zone). Simply said: if you see pkg://solaris/entire in the list
|
||||
of upgrades, you should upgrade the global zone to get all possible
|
||||
updates.
|
||||
``pkg update -vn``, because ``pkg update`` hides packages that require
|
||||
newer version of ``pkg://solaris/entire`` (which means that they can be
|
||||
upgraded only from the global zone). If ``pkg://solaris/entire`` is found
|
||||
in the list of upgrades, then the global zone should be updated to get all
|
||||
possible updates. Use ``refresh=True`` to refresh the package database.
|
||||
|
||||
refresh : False
|
||||
Set to ``True`` to force a full pkg DB refresh before listing
|
||||
|
|
|
@ -127,7 +127,7 @@ def upgrade_available(name):
|
|||
return latest_version(name) != ''
|
||||
|
||||
|
||||
def list_upgrades(refresh=True):
|
||||
def list_upgrades(refresh=True, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
List all available package upgrades on this system
|
||||
|
||||
|
|
|
@ -531,7 +531,10 @@ def join_domain(domain,
|
|||
``ou=computers,ou=departm_432,dc=my-company,dc=com``
|
||||
|
||||
:param bool account_exists:
|
||||
Needs to be set to ``True`` to allow re-using an existing account
|
||||
If set to ``True`` the computer will only join the domain if the account
|
||||
already exists. If set to ``False`` the computer account will be created
|
||||
if it does not exist, otherwise it will use the existing account.
|
||||
Default is False
|
||||
|
||||
:param bool restart: Restarts the computer after a successful join
|
||||
|
||||
|
@ -623,7 +626,8 @@ def unjoin_domain(username=None,
|
|||
.. versionadded:: 2015.8.2/2015.5.7
|
||||
|
||||
:param bool disable:
|
||||
Disable the user account in Active Directory. True to disable.
|
||||
Disable the computer account in Active Directory. True to disable.
|
||||
Default is False
|
||||
|
||||
:param bool restart: Restart the computer after successful unjoin
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ class _Zypper(object):
|
|||
__zypper__ = _Zypper()
|
||||
|
||||
|
||||
def list_upgrades(refresh=True):
|
||||
def list_upgrades(refresh=True, **kwargs):
|
||||
'''
|
||||
List all available package upgrades on this system
|
||||
|
||||
|
@ -303,7 +303,13 @@ def list_upgrades(refresh=True):
|
|||
refresh_db()
|
||||
|
||||
ret = dict()
|
||||
for update_node in __zypper__.nolock.xml.call('list-updates').getElementsByTagName('update'):
|
||||
cmd = ['list-updates']
|
||||
if 'fromrepo' in kwargs:
|
||||
repo_name = kwargs['fromrepo']
|
||||
if not isinstance(repo_name, six.string_types):
|
||||
repo_name = str(repo_name)
|
||||
cmd.extend(['--repo', repo_name])
|
||||
for update_node in __zypper__.nolock.xml.call(*cmd).getElementsByTagName('update'):
|
||||
if update_node.getAttribute('kind') == 'package':
|
||||
ret[update_node.getAttribute('name')] = update_node.getAttribute('edition')
|
||||
|
||||
|
|
|
@ -2,7 +2,34 @@
|
|||
'''
|
||||
Disk monitoring state
|
||||
|
||||
Monitor the state of disk resources
|
||||
Monitor the state of disk resources.
|
||||
|
||||
The ``disk.status`` function can be used to report that the used space of a
|
||||
filesystem is within the specified limits.
|
||||
|
||||
.. code-block:: sls
|
||||
|
||||
used_space:
|
||||
disk.status:
|
||||
- name: /dev/xda1
|
||||
- maximum: 79%
|
||||
- minumum: 11%
|
||||
|
||||
It can be used with an ``onfail`` requisite, for example, to take additional
|
||||
action in response to or in preparation for other states.
|
||||
|
||||
.. code-block:: sls
|
||||
|
||||
storage_threshold:
|
||||
disk.status:
|
||||
- name: /dev/xda1
|
||||
- maximum: 97%
|
||||
|
||||
clear_cache:
|
||||
cmd.run:
|
||||
- name: rm -r /var/cache/app
|
||||
- onfail:
|
||||
- disk: storage_threshold
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
@ -14,9 +41,37 @@ __monitor__ = [
|
|||
]
|
||||
|
||||
|
||||
def _validate_percent(name, value):
|
||||
'''
|
||||
Validate ``name`` as an integer in the range [0, 100]
|
||||
'''
|
||||
comment = ''
|
||||
# Must be integral
|
||||
try:
|
||||
if isinstance(value, string_types):
|
||||
value = value.strip('%')
|
||||
value = int(value)
|
||||
except (TypeError, ValueError):
|
||||
comment += '{0} must be an integer '.format(name)
|
||||
# Must be in percent range
|
||||
else:
|
||||
if value < 0 or value > 100:
|
||||
comment += '{0} must be in the range [0, 100] '.format(name)
|
||||
return value, comment
|
||||
|
||||
|
||||
def status(name, maximum=None, minimum=None):
|
||||
'''
|
||||
Return the current disk usage stats for the named mount point
|
||||
|
||||
name
|
||||
Filesystem with which to check used space
|
||||
|
||||
minimum
|
||||
The required minimum amount of used space in percent
|
||||
|
||||
maximum
|
||||
The required maximum amount of used space in percent
|
||||
'''
|
||||
# Monitoring state, no changes will be made so no test interface needed
|
||||
ret = {'name': name,
|
||||
|
@ -26,38 +81,36 @@ def status(name, maximum=None, minimum=None):
|
|||
'data': {}} # Data field for monitoring state
|
||||
|
||||
data = __salt__['disk.usage']()
|
||||
|
||||
# Validate name
|
||||
if name not in data:
|
||||
ret['result'] = False
|
||||
ret['comment'] += 'Named disk mount not present '
|
||||
return ret
|
||||
# Validate extrema
|
||||
if maximum:
|
||||
try:
|
||||
if isinstance(maximum, string_types):
|
||||
maximum = int(maximum.strip('%'))
|
||||
except Exception:
|
||||
ret['comment'] += 'Max argument must be an integer '
|
||||
maximum, comment = _validate_percent('maximum', maximum)
|
||||
ret['comment'] += comment
|
||||
if minimum:
|
||||
try:
|
||||
if isinstance(minimum, string_types):
|
||||
minimum = int(minimum.strip('%'))
|
||||
except Exception:
|
||||
ret['comment'] += 'Min argument must be an integer '
|
||||
if minimum and maximum:
|
||||
minimum, comment = _validate_percent('minimum', minimum)
|
||||
ret['comment'] += comment
|
||||
if minimum is not None and maximum is not None:
|
||||
if minimum >= maximum:
|
||||
ret['comment'] += 'Min must be less than max'
|
||||
ret['comment'] += 'Min must be less than max '
|
||||
if ret['comment']:
|
||||
return ret
|
||||
cap = int(data[name]['capacity'].strip('%'))
|
||||
|
||||
capacity = int(data[name]['capacity'].strip('%'))
|
||||
ret['data'] = data[name]
|
||||
if minimum:
|
||||
if cap < minimum:
|
||||
ret['comment'] = 'Disk is below minimum of {0} at {1}'.format(
|
||||
minimum, cap)
|
||||
if minimum is not None:
|
||||
if capacity < minimum:
|
||||
ret['comment'] = 'Disk used space is below minimum of {0}% at {1}%'.format(
|
||||
minimum, capacity)
|
||||
return ret
|
||||
if maximum:
|
||||
if cap > maximum:
|
||||
ret['comment'] = 'Disk is above maximum of {0} at {1}'.format(
|
||||
maximum, cap)
|
||||
if maximum is not None:
|
||||
if capacity > maximum:
|
||||
ret['comment'] = 'Disk used space is above maximum of {0}% at {1}%'.format(
|
||||
maximum, capacity)
|
||||
return ret
|
||||
ret['comment'] = 'Disk in acceptable range'
|
||||
ret['result'] = True
|
||||
|
|
|
@ -1860,7 +1860,7 @@ def directory(name,
|
|||
.. code-block:: yaml
|
||||
|
||||
/var/log/httpd:
|
||||
file.directory:
|
||||
file.directory:
|
||||
- user: root
|
||||
- group: root
|
||||
- dir_mode: 755
|
||||
|
@ -1875,7 +1875,7 @@ def directory(name,
|
|||
.. code-block:: yaml
|
||||
|
||||
/var/log/httpd:
|
||||
file.directory:
|
||||
file.directory:
|
||||
- user: root
|
||||
- group: root
|
||||
- dir_mode: 755
|
||||
|
@ -4725,12 +4725,12 @@ def mknod(name, ntype, major=0, minor=0, user=None, group=None, mode='0600'):
|
|||
- group: root
|
||||
- mode: 660
|
||||
|
||||
/dev/fifo:
|
||||
file.mknod:
|
||||
- ntype: p
|
||||
- user: root
|
||||
- group: root
|
||||
- mode: 660
|
||||
/dev/fifo:
|
||||
file.mknod:
|
||||
- ntype: p
|
||||
- user: root
|
||||
- group: root
|
||||
- mode: 660
|
||||
|
||||
.. versionadded:: 0.17.0
|
||||
'''
|
||||
|
|
|
@ -2064,14 +2064,19 @@ def uptodate(name, refresh=False, **kwargs):
|
|||
ret['comment'] = 'State pkg.uptodate is not available'
|
||||
return ret
|
||||
|
||||
# emerge --update doesn't appear to support repo notation
|
||||
if 'fromrepo' in kwargs and __grains__['os'] == 'Gentoo':
|
||||
ret['comment'] = '\'fromrepo\' argument not supported on this platform'
|
||||
return ret
|
||||
|
||||
if isinstance(refresh, bool):
|
||||
try:
|
||||
packages = __salt__['pkg.list_upgrades'](refresh=refresh)
|
||||
packages = __salt__['pkg.list_upgrades'](refresh=refresh, **kwargs)
|
||||
except Exception as exc:
|
||||
ret['comment'] = str(exc)
|
||||
return ret
|
||||
else:
|
||||
ret['comment'] = 'refresh must be a boolean'
|
||||
ret['comment'] = 'refresh must be either True or False'
|
||||
return ret
|
||||
|
||||
if not packages:
|
||||
|
|
|
@ -41,6 +41,54 @@ class BatchTest(integration.ShellCase):
|
|||
cmd = sorted(self.run_salt('\'*\' test.echo \'batch testing\' -b 50%'))
|
||||
self.assertListEqual(cmd, ret)
|
||||
|
||||
def test_batch_run_number(self):
|
||||
'''
|
||||
Tests executing a simple batch command using a number division instead of
|
||||
a percentage with full batch CLI call.
|
||||
'''
|
||||
ret = ['',
|
||||
"Executing run on ['sub_minion', 'minion']",
|
||||
'',
|
||||
'retcode:',
|
||||
' 0',
|
||||
'sub_minion:',
|
||||
' True',
|
||||
'minion:',
|
||||
' True',
|
||||
'retcode:',
|
||||
' 0']
|
||||
cmd = sorted(self.run_salt('\'*\' test.ping --batch-size 2'))
|
||||
self.assertListEqual(cmd, sorted(ret))
|
||||
|
||||
def test_batch_run_grains_targeting(self):
|
||||
'''
|
||||
Tests executing a batch command using a percentage divisor as well as grains
|
||||
targeting.
|
||||
'''
|
||||
os_grain = ''
|
||||
ret = ['',
|
||||
"Executing run on ['sub_minion']",
|
||||
'',
|
||||
'retcode:',
|
||||
' 0',
|
||||
'sub_minion:',
|
||||
' True',
|
||||
'',
|
||||
"Executing run on ['minion']",
|
||||
'',
|
||||
'minion:',
|
||||
' True',
|
||||
'retcode:',
|
||||
' 0']
|
||||
|
||||
for item in self.run_salt('minion grains.get os'):
|
||||
if item != 'minion':
|
||||
os_grain = item
|
||||
|
||||
os_grain = os_grain.strip()
|
||||
cmd = sorted(self.run_salt('-G \'os:{0}\' -b 25% test.ping'.format(os_grain)))
|
||||
self.assertListEqual(cmd, sorted(ret))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
|
|
@ -5,7 +5,6 @@ Integration tests for Ruby Gem module
|
|||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
|
||||
# Import Salt Testing libs
|
||||
from salttesting import skipIf
|
||||
|
@ -17,15 +16,11 @@ import integration
|
|||
import salt.utils
|
||||
import salt.utils.http
|
||||
|
||||
GEM = 'rake'
|
||||
GEM_VER = '11.1.2'
|
||||
GEM = 'tidy'
|
||||
GEM_VER = '1.1.2'
|
||||
OLD_GEM = 'thor'
|
||||
OLD_VERSION = '0.17.0'
|
||||
DEFAULT_GEMS = ['bigdecimal', 'rake', 'json', 'rdoc']
|
||||
|
||||
ON_UBUNTU = False
|
||||
if 'Ubuntu' in platform.dist():
|
||||
ON_UBUNTU = True
|
||||
GEM_LIST = [GEM, OLD_GEM]
|
||||
|
||||
|
||||
def check_status():
|
||||
|
@ -80,18 +75,16 @@ class GemModuleTest(integration.ModuleCase):
|
|||
'''
|
||||
gem.list
|
||||
'''
|
||||
self.run_function('gem.install', [GEM])
|
||||
self.run_function('gem.install', [' '.join(GEM_LIST)])
|
||||
|
||||
all_ret = self.run_function('gem.list')
|
||||
if not ON_UBUNTU:
|
||||
for gem in DEFAULT_GEMS:
|
||||
self.assertIn(gem, all_ret)
|
||||
for gem in GEM_LIST:
|
||||
self.assertIn(gem, all_ret)
|
||||
|
||||
single_ret = self.run_function('gem.list', [GEM])
|
||||
self.assertIn(GEM, single_ret)
|
||||
self.assertIn(GEM_VER, single_ret[GEM])
|
||||
|
||||
self.run_function('gem.uninstall', [GEM])
|
||||
self.run_function('gem.uninstall', [' '.join(GEM_LIST)])
|
||||
|
||||
def test_list_upgrades(self):
|
||||
'''
|
||||
|
|
|
@ -11,10 +11,12 @@ import traceback
|
|||
# Import Salt Testing Libs
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
from salttesting.mixins import RUNTIME_VARS
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt libs
|
||||
import integration
|
||||
import salt.config
|
||||
from salt.output import display_output
|
||||
import salt.config
|
||||
|
||||
|
@ -86,7 +88,7 @@ class OutputReturnTest(integration.ShellCase):
|
|||
'''
|
||||
Tests outputter reliability with utf8
|
||||
'''
|
||||
opts = salt.config.minion_config(os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "minion"))
|
||||
opts = salt.config.minion_config(os.path.join(RUNTIME_VARS.TMP_CONF_DIR, 'minion'))
|
||||
opts['output_file'] = os.path.join(
|
||||
opts['root_dir'], 'outputtest')
|
||||
data = {'foo': {'result': False,
|
||||
|
@ -94,7 +96,7 @@ class OutputReturnTest(integration.ShellCase):
|
|||
'comment': u'ééééàààà'}}
|
||||
try:
|
||||
# this should not raises UnicodeEncodeError
|
||||
display_output(data, opts=self.minion_opts)
|
||||
display_output(data, opts=opts)
|
||||
self.assertTrue(True)
|
||||
except Exception:
|
||||
# display trace in error message for debugging on jenkins
|
||||
|
|
1
tests/unit/acl/__init__.py
Normal file
1
tests/unit/acl/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
# -*- coding: utf-8 -*-
|
61
tests/unit/acl/client_test.py
Normal file
61
tests/unit/acl/client_test.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Libs
|
||||
from salt import acl
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import TestCase, skipIf
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
)
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class ClientACLTestCase(TestCase):
|
||||
'''
|
||||
Unit tests for salt.acl.ClientACL
|
||||
'''
|
||||
def setUp(self):
|
||||
self.blacklist = {
|
||||
'users': ['joker', 'penguin'],
|
||||
'modules': ['cmd.run', 'test.fib'],
|
||||
}
|
||||
|
||||
def test_user_is_blacklisted(self):
|
||||
'''
|
||||
test user_is_blacklisted
|
||||
'''
|
||||
client_acl = acl.PublisherACL(self.blacklist)
|
||||
|
||||
self.assertTrue(client_acl.user_is_blacklisted('joker'))
|
||||
self.assertTrue(client_acl.user_is_blacklisted('penguin'))
|
||||
|
||||
self.assertFalse(client_acl.user_is_blacklisted('batman'))
|
||||
self.assertFalse(client_acl.user_is_blacklisted('robin'))
|
||||
|
||||
def test_cmd_is_blacklisted(self):
|
||||
'''
|
||||
test cmd_is_blacklisted
|
||||
'''
|
||||
client_acl = acl.PublisherACL(self.blacklist)
|
||||
|
||||
self.assertTrue(client_acl.cmd_is_blacklisted('cmd.run'))
|
||||
self.assertTrue(client_acl.cmd_is_blacklisted('test.fib'))
|
||||
|
||||
self.assertFalse(client_acl.cmd_is_blacklisted('cmd.shell'))
|
||||
self.assertFalse(client_acl.cmd_is_blacklisted('test.versions'))
|
||||
|
||||
self.assertTrue(client_acl.cmd_is_blacklisted(['cmd.run', 'state.sls']))
|
||||
self.assertFalse(client_acl.cmd_is_blacklisted(['state.highstate', 'state.sls']))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(ClientACLTestCase, needs_daemon=False)
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
|
||||
Tests for disk state
|
||||
'''
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
@ -26,46 +26,162 @@ disk.__salt__ = {}
|
|||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class DiskTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.disk
|
||||
Test disk state
|
||||
'''
|
||||
# 'status' function tests: 1
|
||||
def setUp(self):
|
||||
'''
|
||||
setup common test info
|
||||
'''
|
||||
self.mock_data = {
|
||||
'/': {
|
||||
'1K-blocks': '41147472',
|
||||
'available': '37087976',
|
||||
'capacity': '6%',
|
||||
'filesystem': '/dev/xvda1',
|
||||
'used': '2172880'},
|
||||
'/dev': {
|
||||
'1K-blocks': '10240',
|
||||
'available': '10240',
|
||||
'capacity': '0%',
|
||||
'filesystem': 'udev',
|
||||
'used': '0'},
|
||||
'/run': {
|
||||
'1K-blocks': '410624',
|
||||
'available': '379460',
|
||||
'capacity': '8%',
|
||||
'filesystem': 'tmpfs',
|
||||
'used': '31164'},
|
||||
'/sys/fs/cgroup': {
|
||||
'1K-blocks': '1026556',
|
||||
'available': '1026556',
|
||||
'capacity': '0%',
|
||||
'filesystem': 'tmpfs',
|
||||
'used': '0'}
|
||||
}
|
||||
self.__salt__ = {
|
||||
'disk.usage': MagicMock(return_value=self.mock_data),
|
||||
}
|
||||
|
||||
def test_status_missing(self):
|
||||
'''
|
||||
Test disk.status when name not found
|
||||
'''
|
||||
mock_fs = '/mnt/cheese'
|
||||
mock_ret = {'name': mock_fs,
|
||||
'result': False,
|
||||
'comment': 'Named disk mount not present ',
|
||||
'changes': {},
|
||||
'data': {}}
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
ret = disk.status(mock_fs)
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
def test_status_type_error(self):
|
||||
'''
|
||||
Test disk.status with incorrectly formatted arguments
|
||||
'''
|
||||
mock_fs = '/'
|
||||
mock_ret = {'name': mock_fs,
|
||||
'result': False,
|
||||
'comment': 'maximum must be an integer ',
|
||||
'changes': {},
|
||||
'data': {}}
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
ret = disk.status(mock_fs, maximum=r'e^{i\pi}')
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
mock_ret['comment'] = 'minimum must be an integer '
|
||||
ret = disk.status(mock_fs, minimum=r'\cos\pi + i\sin\pi')
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
def test_status_range_error(self):
|
||||
'''
|
||||
Test disk.status with excessive extrema
|
||||
'''
|
||||
mock_fs = '/'
|
||||
mock_ret = {'name': mock_fs,
|
||||
'result': False,
|
||||
'comment': 'maximum must be in the range [0, 100] ',
|
||||
'changes': {},
|
||||
'data': {}}
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
ret = disk.status(mock_fs, maximum='-1')
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
mock_ret['comment'] = 'minimum must be in the range [0, 100] '
|
||||
ret = disk.status(mock_fs, minimum='101')
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
def test_status_inverted_range(self):
|
||||
'''
|
||||
Test disk.status when minimum > maximum
|
||||
'''
|
||||
mock_fs = '/'
|
||||
mock_ret = {'name': mock_fs,
|
||||
'result': False,
|
||||
'comment': 'Min must be less than max ',
|
||||
'changes': {},
|
||||
'data': {}}
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
ret = disk.status(mock_fs, maximum='0', minimum='1')
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
def test_status_threshold(self):
|
||||
'''
|
||||
Test disk.status when filesystem triggers thresholds
|
||||
'''
|
||||
mock_min = 100
|
||||
mock_max = 0
|
||||
mock_fs = '/'
|
||||
mock_used = int(self.mock_data[mock_fs]['capacity'].strip('%'))
|
||||
mock_ret = {'name': mock_fs,
|
||||
'result': False,
|
||||
'comment': '',
|
||||
'changes': {},
|
||||
'data': self.mock_data[mock_fs]}
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
mock_ret['comment'] = 'Disk used space is below minimum of {0}% at {1}%'.format(
|
||||
mock_min,
|
||||
mock_used
|
||||
)
|
||||
ret = disk.status(mock_fs, minimum=mock_min)
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
mock_ret['comment'] = 'Disk used space is above maximum of {0}% at {1}%'.format(
|
||||
mock_max,
|
||||
mock_used
|
||||
)
|
||||
ret = disk.status(mock_fs, maximum=mock_max)
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
def test_status(self):
|
||||
'''
|
||||
Test to return the current disk usage stats for the named mount point
|
||||
Test disk.status when filesystem meets thresholds
|
||||
'''
|
||||
name = 'mydisk'
|
||||
mock_min = 0
|
||||
mock_max = 100
|
||||
mock_fs = '/'
|
||||
mock_ret = {'name': mock_fs,
|
||||
'result': True,
|
||||
'comment': 'Disk in acceptable range',
|
||||
'changes': {},
|
||||
'data': self.mock_data[mock_fs]}
|
||||
|
||||
ret = {'name': name,
|
||||
'result': False,
|
||||
'comment': '',
|
||||
'changes': {},
|
||||
'data': {}}
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
ret = disk.status(mock_fs, minimum=mock_min)
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
mock = MagicMock(side_effect=[[], [name], {name: {'capacity': '8 %'}},
|
||||
{name: {'capacity': '22 %'}},
|
||||
{name: {'capacity': '15 %'}}])
|
||||
with patch.dict(disk.__salt__, {'disk.usage': mock}):
|
||||
comt = ('Named disk mount not present ')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(disk.status(name), ret)
|
||||
|
||||
comt = ('Min must be less than max')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(disk.status(name, '10 %', '20 %'), ret)
|
||||
|
||||
comt = ('Disk is below minimum of 10 at 8')
|
||||
ret.update({'comment': comt, 'data': {'capacity': '8 %'}})
|
||||
self.assertDictEqual(disk.status(name, '20 %', '10 %'), ret)
|
||||
|
||||
comt = ('Disk is above maximum of 20 at 22')
|
||||
ret.update({'comment': comt, 'data': {'capacity': '22 %'}})
|
||||
self.assertDictEqual(disk.status(name, '20 %', '10 %'), ret)
|
||||
|
||||
comt = ('Disk in acceptable range')
|
||||
ret.update({'comment': comt, 'result': True,
|
||||
'data': {'capacity': '15 %'}})
|
||||
self.assertDictEqual(disk.status(name, '20 %', '10 %'), ret)
|
||||
with patch.dict(disk.__salt__, self.__salt__):
|
||||
ret = disk.status(mock_fs, maximum=mock_max)
|
||||
self.assertEqual(ret, mock_ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Add table
Reference in a new issue