mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2015.8' into '2016.3'
Conflicts: - salt/cli/salt.py - salt/modules/grains.py - tests/unit/modules/boto_vpc_test.py
This commit is contained in:
commit
318c2ed6a1
8 changed files with 185 additions and 27 deletions
|
@ -130,7 +130,7 @@ Next, let's run the state we created. Open a terminal on the master and run:
|
|||
salt '*' state.apply
|
||||
|
||||
Our master is instructing all targeted minions to run :func:`state.apply
|
||||
<salt.modules.state.apply>`. When this function is executied without any SLS
|
||||
<salt.modules.state.apply>`. When this function is executed without any SLS
|
||||
targets, a minion will download the :ref:`top file <states-top>` and attempt to
|
||||
match the expressions within it. When the minion does match an expression the
|
||||
modules listed for it will be downloaded, compiled, and executed.
|
||||
|
|
|
@ -68,7 +68,8 @@ def beacon(config):
|
|||
|
||||
'''
|
||||
ret = []
|
||||
for mount in config:
|
||||
for mounts in config:
|
||||
mount = mounts.keys()[0]
|
||||
|
||||
try:
|
||||
_current_usage = psutil.disk_usage(mount)
|
||||
|
@ -78,7 +79,7 @@ def beacon(config):
|
|||
continue
|
||||
|
||||
current_usage = _current_usage.percent
|
||||
monitor_usage = config[mount]
|
||||
monitor_usage = mounts[mount]
|
||||
if '%' in monitor_usage:
|
||||
monitor_usage = re.sub('%', '', monitor_usage)
|
||||
monitor_usage = float(monitor_usage)
|
||||
|
|
|
@ -193,7 +193,9 @@ def setvals(grains, destructive=False):
|
|||
'''
|
||||
Set new grains values in the grains config file
|
||||
|
||||
:param Destructive: If an operation results in a key being removed, delete the key, too. Defaults to False.
|
||||
destructive
|
||||
If an operation results in a key being removed, delete the key, too.
|
||||
Defaults to False.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -279,7 +281,15 @@ def setval(key, val, destructive=False):
|
|||
'''
|
||||
Set a grains value in the grains config file
|
||||
|
||||
:param Destructive: If an operation results in a key being removed, delete the key, too. Defaults to False.
|
||||
key
|
||||
The grain key to be set.
|
||||
|
||||
val
|
||||
The value to set the grain key to.
|
||||
|
||||
destructive
|
||||
If an operation results in a key being removed, delete the key, too.
|
||||
Defaults to False.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -305,11 +315,13 @@ def append(key, val, convert=False, delimiter=DEFAULT_TARGET_DELIM):
|
|||
val
|
||||
The value to append to the grain key
|
||||
|
||||
:param convert: If convert is True, convert non-list contents into a list.
|
||||
convert
|
||||
If convert is True, convert non-list contents into a list.
|
||||
If convert is False and the grain contains non-list contents, an error
|
||||
is given. Defaults to False.
|
||||
|
||||
:param delimiter: The key can be a nested dict key. Use this parameter to
|
||||
delimiter
|
||||
The key can be a nested dict key. Use this parameter to
|
||||
specify the delimiter you use, instead of the default ``:``.
|
||||
You can now append values to a list in nested dictionary grains. If the
|
||||
list doesn't exist at this level, it will be created.
|
||||
|
@ -351,12 +363,19 @@ def remove(key, val, delimiter=DEFAULT_TARGET_DELIM):
|
|||
|
||||
Remove a value from a list in the grains config file
|
||||
|
||||
:param delimiter: The key can be a nested dict key. Use this parameter to
|
||||
key
|
||||
The grain key to remove.
|
||||
|
||||
val
|
||||
The value to remove.
|
||||
|
||||
delimiter
|
||||
The key can be a nested dict key. Use this parameter to
|
||||
specify the delimiter you use, instead of the default ``:``.
|
||||
You can now append values to a list in nested dictionary grains. If the
|
||||
list doesn't exist at this level, it will be created.
|
||||
|
||||
.. versionadded:: 2016.3.0
|
||||
.. versionadded:: 2015.8.2
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -387,7 +406,11 @@ def delval(key, destructive=False):
|
|||
|
||||
Delete a grain from the grains config file
|
||||
|
||||
:param destructive: Delete the key, too. Defaults to False.
|
||||
key
|
||||
The grain key from which to delete the value.
|
||||
|
||||
destructive
|
||||
Delete the key, too. Defaults to False.
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ def _mine_get(load, opts):
|
|||
|
||||
def update(clear=False):
|
||||
'''
|
||||
Execute the configured functions and send the data back up to the master
|
||||
Execute the configured functions and send the data back up to the master.
|
||||
The functions to be executed are merged from the master config, pillar and
|
||||
minion config under the option "function_cache":
|
||||
|
||||
|
|
|
@ -418,7 +418,6 @@ class GitProvider(object):
|
|||
# Lock file is empty, set pid to 0 so it evaluates as
|
||||
# False.
|
||||
pid = 0
|
||||
#if self.opts.get("gitfs_global_lock") or pid and pid_exists(int(pid)):
|
||||
global_lock_key = self.role + '_global_lock'
|
||||
lock_file = self._get_lock_file(lock_type=lock_type)
|
||||
if self.opts[global_lock_key]:
|
||||
|
@ -442,7 +441,7 @@ class GitProvider(object):
|
|||
'by another master.')
|
||||
log.warning(msg)
|
||||
if failhard:
|
||||
raise
|
||||
raise exc
|
||||
return
|
||||
elif pid and pid_exists(pid):
|
||||
log.warning('Process %d has a %s %s lock (%s)',
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
'''
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
|
||||
# Import Salt Libs
|
||||
import integration
|
||||
import salt.utils
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
@ -24,6 +26,57 @@ from salttesting.helpers import ensure_in_syspath
|
|||
ensure_in_syspath('../../')
|
||||
|
||||
|
||||
class GrainsTargetingTest(integration.ShellCase):
|
||||
'''
|
||||
Integration tests for targeting with grains.
|
||||
'''
|
||||
|
||||
def test_grains_targeting_os_running(self):
|
||||
'''
|
||||
Tests running "salt -G 'os:<system-os>' test.ping and minions both return True
|
||||
'''
|
||||
test_ret = ['sub_minion:', ' True', 'minion:', ' True']
|
||||
|
||||
os_grain = ''
|
||||
for item in self.run_salt('minion grains.get os'):
|
||||
if item != 'minion:':
|
||||
os_grain = item.strip()
|
||||
|
||||
ret = self.run_salt('-G \'os:{0}\' test.ping'.format(os_grain))
|
||||
self.assertEqual(sorted(ret), sorted(test_ret))
|
||||
|
||||
def test_grains_targeting_minion_id_running(self):
|
||||
'''
|
||||
Tests return of each running test minion targeting with minion id grain
|
||||
'''
|
||||
minion = self.run_salt('-G \'id:minion\' test.ping')
|
||||
self.assertEqual(sorted(minion), sorted(['minion:', ' True']))
|
||||
|
||||
sub_minion = self.run_salt('-G \'id:sub_minion\' test.ping')
|
||||
self.assertEqual(sorted(sub_minion), sorted(['sub_minion:', ' True']))
|
||||
|
||||
def test_grains_targeting_disconnected(self):
|
||||
'''
|
||||
Tests return of minion using grains targeting on a disconnected minion.
|
||||
'''
|
||||
test_ret = 'Minion did not return. [Not connected]'
|
||||
|
||||
# Create a minion key, but do not start the "fake" minion. This mimics a
|
||||
# disconnected minion.
|
||||
key_file = os.path.join(self.master_opts['pki_dir'], 'minions', 'disconnected')
|
||||
salt.utils.fopen(key_file, 'a').close()
|
||||
|
||||
# ping disconnected minion and ensure it times out and returns with correct message
|
||||
try:
|
||||
ret = ''
|
||||
for item in self.run_salt('-G \'id:disconnected\' test.ping'):
|
||||
if item != 'disconnected:':
|
||||
ret = item.strip()
|
||||
self.assertEqual(ret, test_ret)
|
||||
finally:
|
||||
os.unlink(key_file)
|
||||
|
||||
|
||||
class SSHGrainsTest(integration.SSHCase):
|
||||
'''
|
||||
Test salt-ssh grains functionality
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Test the grains module
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
|
@ -10,7 +10,8 @@ import time
|
|||
|
||||
# Import Salt Testing libs
|
||||
from salttesting import skipIf
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
from salttesting.helpers import destructiveTest, ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import salt libs
|
||||
|
@ -105,6 +106,75 @@ class TestModulesGrains(integration.ModuleCase):
|
|||
['level1:level2']),
|
||||
'foo')
|
||||
|
||||
|
||||
class GrainsAppendTestCase(integration.ModuleCase):
|
||||
'''
|
||||
Tests written specifically for the grains.append function.
|
||||
'''
|
||||
GRAIN_KEY = 'salttesting-grain-key'
|
||||
GRAIN_VAL = 'my-grain-val'
|
||||
|
||||
@destructiveTest
|
||||
def tearDown(self):
|
||||
test_grain = self.run_function('grains.get', [self.GRAIN_KEY])
|
||||
if test_grain and test_grain == [self.GRAIN_VAL]:
|
||||
self.run_function('grains.remove', [self.GRAIN_KEY, self.GRAIN_VAL])
|
||||
|
||||
@destructiveTest
|
||||
def test_grains_append(self):
|
||||
'''
|
||||
Tests the return of a simple grains.append call.
|
||||
'''
|
||||
ret = self.run_function('grains.append', [self.GRAIN_KEY, self.GRAIN_VAL])
|
||||
self.assertEqual(ret[self.GRAIN_KEY], [self.GRAIN_VAL])
|
||||
|
||||
@destructiveTest
|
||||
def test_grains_append_val_already_present(self):
|
||||
'''
|
||||
Tests the return of a grains.append call when the value is already present in the grains list.
|
||||
'''
|
||||
messaging = 'The val {0} was already in the list salttesting-grain-key'.format(self.GRAIN_VAL)
|
||||
|
||||
# First, make sure the test grain is present
|
||||
self.run_function('grains.append', [self.GRAIN_KEY, self.GRAIN_VAL])
|
||||
|
||||
# Now try to append again
|
||||
ret = self.run_function('grains.append', [self.GRAIN_KEY, self.GRAIN_VAL])
|
||||
self.assertEqual(messaging, ret)
|
||||
|
||||
@destructiveTest
|
||||
def test_grains_append_val_is_list(self):
|
||||
'''
|
||||
Tests the return of a grains.append call when val is passed in as a list.
|
||||
'''
|
||||
second_grain = self.GRAIN_VAL + '-2'
|
||||
ret = self.run_function('grains.append', [self.GRAIN_KEY, [self.GRAIN_VAL, second_grain]])
|
||||
self.assertEqual(ret[self.GRAIN_KEY], [self.GRAIN_VAL, second_grain])
|
||||
|
||||
@destructiveTest
|
||||
def test_grains_append_call_twice(self):
|
||||
'''
|
||||
Tests the return of a grains.append call when the value is already present
|
||||
but also ensure the grain is not listed twice.
|
||||
'''
|
||||
# First, add the test grain.
|
||||
self.run_function('grains.append', [self.GRAIN_KEY, self.GRAIN_VAL])
|
||||
|
||||
# Call the function again, which results in a string message, as tested in
|
||||
# test_grains_append_val_already_present above.
|
||||
self.run_function('grains.append', [self.GRAIN_KEY, self.GRAIN_VAL])
|
||||
|
||||
# Now make sure the grain doesn't show up twice.
|
||||
grains = self.run_function('grains.items')
|
||||
count = 0
|
||||
for grain in grains.keys():
|
||||
if grain == self.GRAIN_KEY:
|
||||
count += 1
|
||||
|
||||
# We should only have hit the grain key once.
|
||||
self.assertEqual(count, 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(TestModulesGrains)
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
from distutils.version import LooseVersion # pylint: disable=import-error,no-name-in-module
|
||||
import pkg_resources
|
||||
from pkg_resources import DistributionNotFound
|
||||
import random
|
||||
import string
|
||||
|
||||
|
@ -92,6 +94,19 @@ def _has_required_boto():
|
|||
return True
|
||||
|
||||
|
||||
def _get_moto_version():
|
||||
'''
|
||||
Returns the moto version
|
||||
'''
|
||||
try:
|
||||
return LooseVersion(moto.__version__)
|
||||
except AttributeError:
|
||||
try:
|
||||
return LooseVersion(pkg_resources.get_distribution('moto').version)
|
||||
except DistributionNotFound:
|
||||
return False
|
||||
|
||||
|
||||
def _has_required_moto():
|
||||
'''
|
||||
Returns True/False boolean depending on if Moto is installed and correct
|
||||
|
@ -100,17 +115,8 @@ def _has_required_moto():
|
|||
if not HAS_MOTO:
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
if LooseVersion(moto.__version__) < LooseVersion(required_moto_version):
|
||||
return False
|
||||
except AttributeError:
|
||||
import pkg_resources
|
||||
from pkg_resources import DistributionNotFound
|
||||
try:
|
||||
if LooseVersion(pkg_resources.get_distribution('moto').version) < LooseVersion(required_moto_version):
|
||||
return False
|
||||
except DistributionNotFound:
|
||||
return False
|
||||
if _get_moto_version() < LooseVersion(required_moto_version):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
@ -506,13 +512,19 @@ class BotoVpcTestCase(BotoVpcTestCaseBase, BotoVpcTestCaseMixin):
|
|||
'''
|
||||
Tests describing parameters via vpc id if vpc exist
|
||||
'''
|
||||
# With moto 0.4.25 is_default is set to True. 0.4.24 and older, is_default is False
|
||||
if _get_moto_version() >= LooseVersion('0.4.25'):
|
||||
is_default = True
|
||||
else:
|
||||
is_default = False
|
||||
|
||||
vpc = self._create_vpc(name='test', tags={'test': 'testvalue'})
|
||||
|
||||
describe_vpc = boto_vpc.describe(vpc_id=vpc.id, **conn_parameters)
|
||||
|
||||
vpc_properties = dict(id=vpc.id,
|
||||
cidr_block=six.text_type(cidr_block),
|
||||
is_default=False,
|
||||
is_default=is_default,
|
||||
state=u'available',
|
||||
tags={u'Name': u'test', u'test': u'testvalue'},
|
||||
dhcp_options_id=u'dopt-7a8b9c2d',
|
||||
|
|
Loading…
Add table
Reference in a new issue