Merge pull request #47107 from twangboy/fix_46932

Fix issues with reg state, add tests
This commit is contained in:
Daniel Wallace 2018-04-18 10:53:01 -05:00 committed by GitHub
commit 50bd885ec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 341 additions and 28 deletions

View file

@ -192,11 +192,8 @@ def present(name,
salt.utils.stringutils.to_unicode(name, 'utf-8'))
return ret
try:
vdata_decoded = salt.utils.stringutils.to_unicode(vdata, 'utf-8')
except UnicodeDecodeError:
# vdata contains binary data that can't be decoded
vdata_decoded = vdata
vdata_decoded = __utils__['reg.cast_vdata'](vdata=vdata, vtype=vtype)
add_change = {'Key': r'{0}\{1}'.format(hive, key),
'Entry': '{0}'.format(salt.utils.stringutils.to_unicode(vname, 'utf-8') if vname else '(Default)'),
'Value': vdata_decoded}

View file

@ -45,6 +45,7 @@ except ImportError:
import salt.utils.platform
import salt.utils.stringutils
from salt.exceptions import CommandExecutionError
from salt.ext import six
PY2 = sys.version_info[0] == 2
log = logging.getLogger(__name__)
@ -169,7 +170,10 @@ def key_exists(hive, key, use_32bit_registry=False):
local_key = _to_unicode(key)
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
access_mask = registry.registry_32[use_32bit_registry]
try:
@ -231,7 +235,10 @@ def list_keys(hive, key=None, use_32bit_registry=False):
local_key = _to_unicode(key)
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
access_mask = registry.registry_32[use_32bit_registry]
subkeys = []
@ -287,7 +294,10 @@ def list_values(hive, key=None, use_32bit_registry=False, include_default=True):
local_key = _to_unicode(key)
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
access_mask = registry.registry_32[use_32bit_registry]
handle = None
values = list()
@ -378,7 +388,10 @@ def read_value(hive, key, vname=None, use_32bit_registry=False):
ret['vname'] = '(Default)'
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
access_mask = registry.registry_32[use_32bit_registry]
try:
@ -524,26 +537,14 @@ def set_value(hive,
local_vtype = _to_unicode(vtype)
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
vtype_value = registry.vtype[local_vtype]
access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
# Check data type and cast to expected type
# int will automatically become long on 64bit numbers
# https://www.python.org/dev/peps/pep-0237/
# String Types to Unicode
if vtype_value in [win32con.REG_SZ, win32con.REG_EXPAND_SZ]:
local_vdata = _to_unicode(vdata)
# Don't touch binary...
elif vtype_value == win32con.REG_BINARY:
local_vdata = vdata
# Make sure REG_MULTI_SZ is a list of strings
elif vtype_value == win32con.REG_MULTI_SZ:
local_vdata = [_to_unicode(i) for i in vdata]
# Everything else is int
else:
local_vdata = int(vdata)
local_vdata = cast_vdata(vdata=vdata, vtype=local_vtype)
if volatile:
create_options = registry.opttype['REG_OPTION_VOLATILE']
@ -563,6 +564,52 @@ def set_value(hive,
return False
def cast_vdata(vdata=None, vtype='REG_SZ'):
'''
Cast the ``vdata` value to the appropriate data type for the registry type
specified in ``vtype``
Args:
vdata (str, list, bin): The data to cast
vtype (str):
The type of data to be written to the registry. Must be one of the
following:
- REG_BINARY
- REG_DWORD
- REG_EXPAND_SZ
- REG_MULTI_SZ
- REG_SZ
Returns:
The vdata cast to the appropriate type. Will be unicode string, binary,
list of unicode strings, or int
'''
# Check data type and cast to expected type
# int will automatically become long on 64bit numbers
# https://www.python.org/dev/peps/pep-0237/
registry = Registry()
vtype_value = registry.vtype[vtype]
# String Types to Unicode
if vtype_value in [win32con.REG_SZ, win32con.REG_EXPAND_SZ]:
return _to_unicode(vdata)
# Don't touch binary... if it's binary
elif vtype_value == win32con.REG_BINARY:
if isinstance(vdata, six.text_type):
# Unicode data must be encoded
return vdata.encode('utf-8')
return vdata
# Make sure REG_MULTI_SZ is a list of strings
elif vtype_value == win32con.REG_MULTI_SZ:
return [_to_unicode(i) for i in vdata]
# Everything else is int
else:
return int(vdata)
def delete_key_recursive(hive, key, use_32bit_registry=False):
'''
.. versionadded:: 2015.5.4
@ -601,7 +648,10 @@ def delete_key_recursive(hive, key, use_32bit_registry=False):
# Instantiate the registry object
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
key_path = local_key
access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
@ -699,7 +749,10 @@ def delete_value(hive, key, vname=None, use_32bit_registry=False):
local_vname = _to_unicode(vname)
registry = Registry()
hkey = registry.hkeys[local_hive]
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError('Invalid Hive: {0}'.format(local_hive))
access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
try:

View file

@ -0,0 +1,262 @@
# -*- coding: utf-8 -*-
'''
Tests for the Reg State
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import logging
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.mixins import SaltReturnAssertsMixin
from tests.support.unit import skipIf
from tests.support.helpers import destructiveTest, generate_random_name
# Import Salt libs
import salt.utils.platform
import salt.utils.win_reg as reg
log = logging.getLogger(__name__)
__testcontext__ = {}
UNICODE_VALUE_NAME = 'Unicode Key \N{TRADE MARK SIGN}'
UNICODE_VALUE = 'Unicode Value ' \
'\N{COPYRIGHT SIGN},\N{TRADE MARK SIGN},\N{REGISTERED SIGN}'
FAKE_KEY = 'SOFTWARE\\{0}'.format(generate_random_name('SaltTesting-'))
@destructiveTest
@skipIf(not salt.utils.platform.is_windows(), 'Windows Specific Test')
class RegTest(ModuleCase, SaltReturnAssertsMixin):
'''
Reg state module tests
These tests are destructive as the modify the registry
'''
def tearDown(self):
reg.delete_key_recursive(hive='HKLM',
key=FAKE_KEY)
reg.delete_key_recursive(hive='HKLM',
key=FAKE_KEY,
use_32bit_registry=True)
def test_present_reg_sz(self):
'''
Testing reg.present with REG_SZ
'''
log.debug('Testing reg.present with REG_SZ')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vname='test_reg_sz',
vdata='fake string data')
expected = {
'reg': {
'Added': {
'Entry': 'test_reg_sz',
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': 'fake string data'}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM', key=FAKE_KEY, vname='test_reg_sz')
expected = {
'vtype': 'REG_SZ',
'vname': 'test_reg_sz',
'success': True,
'hive': 'HKLM',
'vdata': 'fake string data',
'key': FAKE_KEY}
self.assertEqual(ret, expected)
def test_present_reg_sz_unicode_value(self):
'''
Testing reg.present with REG_SZ and a unicode value
'''
log.debug('Testing reg.present with REG_SZ and a unicode value')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vname='test_reg_sz',
vdata=UNICODE_VALUE)
expected = {
'reg': {
'Added': {
'Entry': 'test_reg_sz',
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': UNICODE_VALUE}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM', key=FAKE_KEY, vname='test_reg_sz')
expected = {
'vtype': 'REG_SZ',
'vname': 'test_reg_sz',
'success': True,
'hive': 'HKLM',
'vdata': UNICODE_VALUE,
'key': FAKE_KEY}
self.assertEqual(ret, expected)
def test_present_reg_sz_unicode_default_value(self):
'''
Testing reg.present with REG_SZ and a unicode default value
'''
log.debug('Testing reg.present with REG_SZ and a unicode default value')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vdata=UNICODE_VALUE)
expected = {
'reg': {
'Added': {
'Entry': '(Default)',
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': UNICODE_VALUE}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM', key=FAKE_KEY)
expected = {
'vtype': 'REG_SZ',
'vname': '(Default)',
'success': True,
'hive': 'HKLM',
'vdata': UNICODE_VALUE,
'key': FAKE_KEY}
self.assertEqual(ret, expected)
def test_present_reg_sz_unicode_value_name(self):
'''
Testing reg.present with REG_SZ and a unicode value name
'''
log.debug('Testing reg.present with REG_SZ and a unicode value name')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vname=UNICODE_VALUE_NAME,
vdata='fake string data')
expected = {
'reg': {
'Added': {
'Entry': UNICODE_VALUE_NAME,
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': 'fake string data'}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM', key=FAKE_KEY, vname=UNICODE_VALUE_NAME)
expected = {
'vtype': 'REG_SZ',
'vname': UNICODE_VALUE_NAME,
'success': True,
'hive': 'HKLM',
'vdata': 'fake string data',
'key': FAKE_KEY}
self.assertEqual(ret, expected)
def test_present_reg_binary(self):
'''
Testing reg.present with REG_BINARY
'''
test_data = 'Salty Test'
log.debug('Testing reg.present with REG_BINARY')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vname='test_reg_binary',
vtype='REG_BINARY',
vdata=test_data)
expected = {
'reg': {
'Added': {
'Entry': 'test_reg_binary',
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': test_data}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM', key=FAKE_KEY, vname='test_reg_binary')
expected = {
'vtype': 'REG_BINARY',
'vname': 'test_reg_binary',
'success': True,
'hive': 'HKLM',
'vdata': test_data.encode('utf-8'),
'key': FAKE_KEY}
self.assertEqual(ret, expected)
def test_present_reg_multi_sz(self):
'''
Testing reg.present with REG_MULTI_SZ
'''
log.debug('Testing reg.present with REG_MULTI_SZ')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vname='test_reg_multi_sz',
vtype='REG_MULTI_SZ',
vdata=['item1', 'item2'])
expected = {
'reg': {
'Added': {
'Entry': 'test_reg_multi_sz',
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': ['item1', 'item2']}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM',
key=FAKE_KEY,
vname='test_reg_multi_sz')
expected = {
'vtype': 'REG_MULTI_SZ',
'vname': 'test_reg_multi_sz',
'success': True,
'hive': 'HKLM',
'vdata': ['item1', 'item2'],
'key': FAKE_KEY}
self.assertEqual(ret, expected)
def test_present_32_bit(self):
'''
Testing reg.present with REG_SZ using 32bit registry
'''
log.debug('Testing reg.present with REG_SZ using 32bit registry')
# default type is 'REG_SZ'
# Does the state return the correct data
ret = self.run_state('reg.present',
name='HKLM\\{0}'.format(FAKE_KEY),
vname='test_reg_sz',
vdata='fake string data',
use_32bit_registry=True)
expected = {
'reg': {
'Added': {
'Entry': 'test_reg_sz',
'Key': 'HKLM\\{0}'.format(FAKE_KEY),
'Value': 'fake string data'}}}
self.assertSaltStateChangesEqual(ret, expected)
# Is the value actually set
ret = reg.read_value(hive='HKLM',
key=FAKE_KEY,
vname='test_reg_sz',
use_32bit_registry=True)
expected = {
'vtype': 'REG_SZ',
'vname': 'test_reg_sz',
'success': True,
'hive': 'HKLM',
'vdata': 'fake string data',
'key': FAKE_KEY}
self.assertEqual(ret, expected)

View file

@ -27,6 +27,7 @@ integration.runners.test_jobs
integration.runners.test_salt
integration.sdb.test_env
integration.states.test_host
integration.states.test_reg
integration.states.test_renderers
integration.utils.testprogram
integration.wheel.test_client