Merge pull request #34025 from rallytime/merge-2016.3

[2016.3] Merge forward from 2015.8 to 2016.3
This commit is contained in:
Nicole Thomas 2016-06-15 15:41:00 -04:00 committed by GitHub
parent 3035520594
commit f546a00dc9
24 changed files with 470 additions and 160 deletions

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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):

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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 = ''

View file

@ -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 = []

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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

View file

@ -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
'''

View file

@ -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:

View file

@ -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

View file

@ -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):
'''

View file

@ -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

View file

@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View 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)

View file

@ -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__':