Merge branch '2019.2.1' into fix_lock_1740_lgpo

This commit is contained in:
Shane Lee 2019-07-02 22:43:03 -06:00 committed by GitHub
commit 62450db373
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 149 additions and 52 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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