mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2019.2.1' into fix_lock_1740_lgpo
This commit is contained in:
commit
62450db373
11 changed files with 149 additions and 52 deletions
|
@ -243,10 +243,6 @@ New-Item -Path "$($ini['Settings']['SitePkgs2Dir'])\win32com\gen_py" -ItemType D
|
|||
Write-Output " - $script_name :: Removing pywin32_system32 Directory . . ."
|
||||
Remove-Item "$($ini['Settings']['SitePkgs2Dir'])\pywin32_system32"
|
||||
|
||||
# Remove pythonwin directory
|
||||
Write-Output " - $script_name :: Removing pythonwin Directory . . ."
|
||||
Remove-Item "$($ini['Settings']['SitePkgs2Dir'])\pythonwin" -Force -Recurse
|
||||
|
||||
# Remove PyWin32 PostInstall and testall Scripts
|
||||
Write-Output " - $script_name :: Removing PyWin32 scripts . . ."
|
||||
Remove-Item "$($ini['Settings']['Scripts2Dir'])\pywin32_*" -Force -Recurse
|
||||
|
|
|
@ -241,10 +241,6 @@ New-Item -Path "$($ini['Settings']['SitePkgs3Dir'])\win32com\gen_py" -ItemType D
|
|||
Write-Output " - $script_name :: Removing pywin32_system32 Directory . . ."
|
||||
Remove-Item "$($ini['Settings']['SitePkgs3Dir'])\pywin32_system32"
|
||||
|
||||
# Remove pythonwin directory
|
||||
Write-Output " - $script_name :: Removing pythonwin Directory . . ."
|
||||
Remove-Item "$($ini['Settings']['SitePkgs3Dir'])\pythonwin" -Force -Recurse
|
||||
|
||||
# Remove PyWin32 PostInstall and testall Scripts
|
||||
Write-Output " - $script_name :: Removing PyWin32 scripts . . ."
|
||||
Remove-Item "$($ini['Settings']['Scripts3Dir'])\pywin32_*" -Force -Recurse
|
||||
|
|
|
@ -5728,6 +5728,18 @@ def _checkValueItemParent(policy_element, policy_name, policy_key,
|
|||
return False
|
||||
|
||||
|
||||
def _encode_string(value):
|
||||
encoded_null = chr(0).encode('utf-16-le')
|
||||
if value is None:
|
||||
return encoded_null
|
||||
else:
|
||||
# Should we raise an error here, or attempt to cast to a string
|
||||
if not isinstance(value, six.string_types):
|
||||
raise TypeError('Value {0} is not a string type\n'
|
||||
'Type: {1}'.format(repr(value), type(value)))
|
||||
return b''.join([value.encode('utf-16-le'), encoded_null])
|
||||
|
||||
|
||||
def _buildKnownDataSearchString(reg_key, reg_valueName, reg_vtype, reg_data,
|
||||
check_deleted=False):
|
||||
'''
|
||||
|
@ -5749,8 +5761,7 @@ def _buildKnownDataSearchString(reg_key, reg_valueName, reg_vtype, reg_data,
|
|||
elif reg_vtype == "REG_QWORD":
|
||||
this_element_value = struct.pack(b'Q', int(reg_data))
|
||||
elif reg_vtype == 'REG_SZ':
|
||||
this_element_value = b''.join([reg_data.encode('utf-16-le'),
|
||||
encoded_null])
|
||||
this_element_value = _encode_string(reg_data)
|
||||
if check_deleted:
|
||||
reg_vtype = 'REG_SZ'
|
||||
expected_string = b''.join(['['.encode('utf-16-le'),
|
||||
|
@ -5845,8 +5856,7 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
|
|||
return None
|
||||
elif etree.QName(element).localname == 'string':
|
||||
this_vtype = 'REG_SZ'
|
||||
this_element_value = b''.join([element.text.encode('utf-16-le'),
|
||||
encoded_null])
|
||||
this_element_value = _encode_string(element.text)
|
||||
elif etree.QName(parent_element).localname == 'elements':
|
||||
standard_element_expected_string = True
|
||||
if etree.QName(element).localname == 'boolean':
|
||||
|
@ -5889,9 +5899,7 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
|
|||
if 'expandable' in element.attrib:
|
||||
if element.attrib['expandable'].lower() == 'true':
|
||||
this_vtype = 'REG_EXPAND_SZ'
|
||||
if this_element_value is not None:
|
||||
this_element_value = b''.join([this_element_value.encode('utf-16-le'),
|
||||
encoded_null])
|
||||
this_element_value = _encode_string(this_element_value)
|
||||
elif etree.QName(element).localname == 'multiText':
|
||||
this_vtype = 'REG_MULTI_SZ' if not check_deleted else 'REG_SZ'
|
||||
if this_element_value is not None:
|
||||
|
@ -5959,8 +5967,7 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
|
|||
six.unichr(len('{0}{1}'.format(element_values[i],
|
||||
chr(0)).encode('utf-16-le'))).encode('utf-32-le'),
|
||||
encoded_semicolon,
|
||||
b''.join([element_values[i].encode('utf-16-le'),
|
||||
encoded_null]),
|
||||
_encode_string(element_values[i]),
|
||||
']'.encode('utf-16-le')])
|
||||
else:
|
||||
expected_string = del_keys + b''.join(['['.encode('utf-16-le'),
|
||||
|
|
|
@ -47,6 +47,37 @@ TARGET_REX = re.compile(
|
|||
)
|
||||
|
||||
|
||||
def _nodegroup_regex(nodegroup, words, opers):
|
||||
opers_set = set(opers)
|
||||
ret = words
|
||||
if (set(ret) - opers_set) == set(ret):
|
||||
# No compound operators found in nodegroup definition. Check for
|
||||
# group type specifiers
|
||||
group_type_re = re.compile('^[A-Z]@')
|
||||
regex_chars = ['(', '[', '{', '\\', '?', '}', ']', ')']
|
||||
if not [x for x in ret if '*' in x or group_type_re.match(x)]:
|
||||
# No group type specifiers and no wildcards.
|
||||
# Treat this as an expression.
|
||||
if [x for x in ret if x in [x for y in regex_chars if y in x]]:
|
||||
joined = 'E@' + ','.join(ret)
|
||||
log.debug(
|
||||
'Nodegroup \'%s\' (%s) detected as an expression. '
|
||||
'Assuming compound matching syntax of \'%s\'',
|
||||
nodegroup, ret, joined
|
||||
)
|
||||
else:
|
||||
# Treat this as a list of nodenames.
|
||||
joined = 'L@' + ','.join(ret)
|
||||
log.debug(
|
||||
'Nodegroup \'%s\' (%s) detected as list of nodenames. '
|
||||
'Assuming compound matching syntax of \'%s\'',
|
||||
nodegroup, ret, joined
|
||||
)
|
||||
# Return data must be a list of compound matching components
|
||||
# to be fed into compound matcher. Enclose return data in list.
|
||||
return [joined]
|
||||
|
||||
|
||||
def parse_target(target_expression):
|
||||
'''Parse `target_expressing` splitting it into `engine`, `delimiter`,
|
||||
`pattern` - returns a dict'''
|
||||
|
@ -141,36 +172,16 @@ def nodegroup_comp(nodegroup, nodegroups, skip=None, first_call=True):
|
|||
# Only return list form if a nodegroup was expanded. Otherwise return
|
||||
# the original string to conserve backwards compat
|
||||
if expanded_nodegroup or not first_call:
|
||||
if not first_call:
|
||||
joined = _nodegroup_regex(nodegroup, words, opers)
|
||||
if joined:
|
||||
return joined
|
||||
return ret
|
||||
else:
|
||||
opers_set = set(opers)
|
||||
ret = words
|
||||
if (set(ret) - opers_set) == set(ret):
|
||||
# No compound operators found in nodegroup definition. Check for
|
||||
# group type specifiers
|
||||
group_type_re = re.compile('^[A-Z]@')
|
||||
regex_chars = ['(', '[', '{', '\\', '?', '}', ']', ')']
|
||||
if not [x for x in ret if '*' in x or group_type_re.match(x)]:
|
||||
# No group type specifiers and no wildcards.
|
||||
# Treat this as an expression.
|
||||
if [x for x in ret if x in [x for y in regex_chars if y in x]]:
|
||||
joined = 'E@' + ','.join(ret)
|
||||
log.debug(
|
||||
'Nodegroup \'%s\' (%s) detected as an expression. '
|
||||
'Assuming compound matching syntax of \'%s\'',
|
||||
nodegroup, ret, joined
|
||||
)
|
||||
else:
|
||||
# Treat this as a list of nodenames.
|
||||
joined = 'L@' + ','.join(ret)
|
||||
log.debug(
|
||||
'Nodegroup \'%s\' (%s) detected as list of nodenames. '
|
||||
'Assuming compound matching syntax of \'%s\'',
|
||||
nodegroup, ret, joined
|
||||
)
|
||||
# Return data must be a list of compound matching components
|
||||
# to be fed into compound matcher. Enclose return data in list.
|
||||
return [joined]
|
||||
joined = _nodegroup_regex(nodegroup, ret, opers)
|
||||
if joined:
|
||||
return joined
|
||||
|
||||
log.debug(
|
||||
'No nested nodegroups detected. Using original nodegroup '
|
||||
|
|
|
@ -70,14 +70,22 @@ nodegroups:
|
|||
min: minion
|
||||
sub_min: sub_minion
|
||||
mins: N@min or N@sub_min
|
||||
list_nodegroup:
|
||||
- 'minion'
|
||||
- 'sub_minion'
|
||||
multiline_nodegroup:
|
||||
- 'minion'
|
||||
- 'or'
|
||||
- 'sub_minion'
|
||||
one_minion_list:
|
||||
- 'minion'
|
||||
redundant_minions: N@min or N@mins
|
||||
nodegroup_loop_a: N@nodegroup_loop_b
|
||||
nodegroup_loop_b: N@nodegroup_loop_a
|
||||
missing_minion: L@minion,ghostminion
|
||||
list_group: N@multiline_nodegroup
|
||||
one_list_group: N@one_minion_list
|
||||
list_group2: N@list_nodegroup
|
||||
|
||||
|
||||
mysql.host: localhost
|
||||
|
|
|
@ -17,7 +17,7 @@ import salt.utils.platform
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@flaky(attempts=10)
|
||||
@skipIf(not salt.utils.platform.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.path.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacPowerModuleTest(ModuleCase):
|
||||
|
@ -142,7 +142,7 @@ class MacPowerModuleTest(ModuleCase):
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@flaky(attempts=10)
|
||||
@skipIf(not salt.utils.platform.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.path.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacPowerModuleTestSleepOnPowerButton(ModuleCase):
|
||||
|
@ -193,7 +193,7 @@ class MacPowerModuleTestSleepOnPowerButton(ModuleCase):
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@flaky(attempts=10)
|
||||
@skipIf(not salt.utils.platform.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.path.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacPowerModuleTestRestartPowerFailure(ModuleCase):
|
||||
|
@ -243,7 +243,7 @@ class MacPowerModuleTestRestartPowerFailure(ModuleCase):
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@flaky(attempts=10)
|
||||
@skipIf(not salt.utils.platform.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.path.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacPowerModuleTestWakeOnNet(ModuleCase):
|
||||
|
@ -290,7 +290,7 @@ class MacPowerModuleTestWakeOnNet(ModuleCase):
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky
|
||||
@flaky(attempts=10)
|
||||
@skipIf(not salt.utils.platform.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.path.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacPowerModuleTestWakeOnModem(ModuleCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
integration tests for mac_system
|
||||
integration tests for mac_shadow
|
||||
'''
|
||||
|
||||
# Import Python libs
|
||||
|
@ -40,7 +40,7 @@ NO_USER = __random_string()
|
|||
@skipIf(not salt.utils.path.which('pwpolicy'), '\'pwpolicy\' binary not found in $PATH')
|
||||
class MacShadowModuleTest(ModuleCase):
|
||||
'''
|
||||
Validate the mac_system module
|
||||
Validate the mac_shadow module
|
||||
'''
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -34,7 +34,7 @@ SET_SUBNET_NAME = __random_string()
|
|||
|
||||
|
||||
@skip_if_not_root
|
||||
@flaky(attempts=8)
|
||||
@flaky(attempts=10)
|
||||
@skipIf(not salt.utils.platform.is_darwin(), 'Test only available on macOS')
|
||||
@skipIf(not salt.utils.path.which('systemsetup'), '\'systemsetup\' binary not found in $PATH')
|
||||
class MacSystemModuleTest(ModuleCase):
|
||||
|
|
|
@ -153,6 +153,23 @@ class MatchTest(ShellCase, ShellCaseCommonTestsMixin):
|
|||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertTrue(minion_in_returns('sub_minion', data))
|
||||
|
||||
def test_nodegroup_list(self):
|
||||
data = self.run_salt('-N list_group test.ping')
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertTrue(minion_in_returns('sub_minion', data))
|
||||
|
||||
data = self.run_salt('-N list_group2 test.ping')
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertTrue(minion_in_returns('sub_minion', data))
|
||||
|
||||
data = self.run_salt('-N one_list_group test.ping')
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertFalse(minion_in_returns('sub_minion', data))
|
||||
|
||||
data = self.run_salt('-N one_minion_list test.ping')
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertFalse(minion_in_returns('sub_minion', data))
|
||||
|
||||
def test_glob(self):
|
||||
'''
|
||||
test salt glob matcher
|
||||
|
|
55
tests/unit/modules/test_win_lgpo.py
Normal file
55
tests/unit/modules/test_win_lgpo.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: Shane Lee <slee@saltstack.com>
|
||||
'''
|
||||
|
||||
# Import Python Libs
|
||||
from __future__ import absolute_import, unicode_literals, print_function
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from tests.support.unit import TestCase
|
||||
|
||||
# Import Salt Libs
|
||||
import salt.modules.win_lgpo as win_lgpo
|
||||
|
||||
|
||||
class WinSystemTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.modules.win_lgpo
|
||||
'''
|
||||
encoded_null = chr(0).encode('utf-16-le')
|
||||
|
||||
def test__encode_string(self):
|
||||
'''
|
||||
``_encode_string`` should return a null terminated ``utf-16-le`` encoded
|
||||
string when a string value is passed
|
||||
'''
|
||||
encoded_value = b''.join(['Salt is awesome'.encode('utf-16-le'),
|
||||
self.encoded_null])
|
||||
value = win_lgpo._encode_string('Salt is awesome')
|
||||
self.assertEqual(value, encoded_value)
|
||||
|
||||
def test__encode_string_empty_string(self):
|
||||
'''
|
||||
``_encode_string`` should return an encoded null when an empty string
|
||||
value is passed
|
||||
'''
|
||||
value = win_lgpo._encode_string('')
|
||||
self.assertEqual(value, self.encoded_null)
|
||||
|
||||
def test__encode_string_error(self):
|
||||
'''
|
||||
``_encode_string`` should raise an error if a non-string value is passed
|
||||
'''
|
||||
self.assertRaises(TypeError, win_lgpo._encode_string, [1])
|
||||
test_list = ['item1', 'item2']
|
||||
self.assertRaises(TypeError, win_lgpo._encode_string, [test_list])
|
||||
test_dict = {'key1': 'value1', 'key2': 'value2'}
|
||||
self.assertRaises(TypeError, win_lgpo._encode_string, [test_dict])
|
||||
|
||||
def test__encode_string_none(self):
|
||||
'''
|
||||
``_encode_string`` should return an encoded null when ``None`` is passed
|
||||
'''
|
||||
value = win_lgpo._encode_string(None)
|
||||
self.assertEqual(value, self.encoded_null)
|
|
@ -19,6 +19,9 @@ NODEGROUPS = {
|
|||
'group2': ['G@foo:bar', 'or', 'web1*'],
|
||||
'group3': ['N@group1', 'or', 'N@group2'],
|
||||
'group4': ['host4', 'host5', 'host6'],
|
||||
'group5': 'N@group4',
|
||||
'group6': 'N@group3',
|
||||
'group7': ['host1']
|
||||
}
|
||||
|
||||
EXPECTED = {
|
||||
|
@ -26,6 +29,10 @@ EXPECTED = {
|
|||
'group2': ['G@foo:bar', 'or', 'web1*'],
|
||||
'group3': ['(', '(', 'L@host1,host2,host3', ')', 'or', '(', 'G@foo:bar', 'or', 'web1*', ')', ')'],
|
||||
'group4': ['L@host4,host5,host6'],
|
||||
'group5': ['(', 'L@host4,host5,host6', ')'],
|
||||
'group6': ['(', '(', '(', 'L@host1,host2,host3', ')', 'or', '(',
|
||||
'G@foo:bar', 'or', 'web1*', ')', ')', ')'],
|
||||
'group7': ['L@host1']
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue