Merge branch '2018.3' into bp-52012

This commit is contained in:
Megan Wilhite 2019-03-08 10:30:54 -05:00 committed by GitHub
commit 37666bd433
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 144 additions and 22 deletions

View file

@ -86,7 +86,7 @@ Dependencies
Salt should run on any Unix-like platform so long as the dependencies are met.
* `Python 2.7`_ >= 2.7 <3.0
* `Python`_ - Python2 >= 2.7, Python3 >= 3.4
* `msgpack-python`_ - High-performance message interchange format
* `YAML`_ - Python YAML bindings
* `Jinja2`_ - parsing Salt States (configurable in the master settings)
@ -95,7 +95,7 @@ Salt should run on any Unix-like platform so long as the dependencies are met.
cloud service providers using a unified API
* `Requests`_ - HTTP library
* `Tornado`_ - Web framework and asynchronous networking library
* `futures`_ - Backport of the concurrent.futures package from Python 3.2
* `futures`_ - Python2 only dependency. Backport of the concurrent.futures package from Python 3.2
Depending on the chosen Salt transport, `ZeroMQ`_ or `RAET`_, dependencies
vary:
@ -142,7 +142,7 @@ Optional Dependencies
settings)
* gcc - dynamic `Cython`_ module compiling
.. _`Python 2.7`: http://python.org/download/
.. _`Python`: http://python.org/download/
.. _`ZeroMQ`: http://zeromq.org/
.. _`pyzmq`: https://github.com/zeromq/pyzmq
.. _`msgpack-python`: https://pypi.python.org/pypi/msgpack-python/

View file

@ -7,8 +7,8 @@ Salt compatibility code
# Import python libs
from __future__ import absolute_import, unicode_literals, print_function
import sys
import types
import logging
import binascii
# Import 3rd-party libs
from salt.exceptions import SaltException
@ -173,7 +173,7 @@ class IPv6AddressScoped(ipaddress.IPv6Address):
self._ip = address
elif self._is_packed_binary(address):
self._check_packed_address(address, 16)
self._ip = ipaddress._int_from_bytes(address, 'big')
self._ip = int(binascii.hexlify(address), 16)
else:
address = str(address)
if '/' in address:
@ -190,7 +190,7 @@ class IPv6AddressScoped(ipaddress.IPv6Address):
packed = False
if isinstance(data, bytes) and len(data) == 16 and b':' not in data:
try:
packed = bool(int(str(bytearray(data)).encode('hex'), 16))
packed = bool(int(binascii.hexlify(data), 16))
except ValueError:
pass

View file

@ -1828,7 +1828,7 @@ def create_disk(kwargs=None, call=None):
)
return False
if 'size' is None and 'image' is None and 'snapshot' is None:
if size is None and image is None and snapshot is None:
log.error(
'Must specify image, snapshot, or size.'
)

View file

@ -157,14 +157,13 @@ def _windows_disks():
namespace = r'\\root\microsoft\windows\storage'
path = 'MSFT_PhysicalDisk'
where = '(MediaType=3 or MediaType=4)'
get = 'DeviceID,MediaType'
ret = {'disks': [], 'SSDs': []}
cmdret = __salt__['cmd.run_all'](
'{0} /namespace:{1} path {2} where {3} get {4} /format:table'.format(
wmic, namespace, path, where, get))
'{0} /namespace:{1} path {2} get {3} /format:table'.format(
wmic, namespace, path, get))
if cmdret['retcode'] != 0:
log.trace('Disk grain does not support this version of Windows')
@ -181,10 +180,12 @@ def _windows_disks():
elif mediatype == '4':
log.trace('Device %s reports itself as an SSD', device)
ret['SSDs'].append(device)
ret['disks'].append(device)
elif mediatype == '5':
log.trace('Device %s reports itself as an SCM', device)
ret['disks'].append(device)
else:
log.trace(
'Unable to identify device %s as an SSD or HDD. It does '
'not report 3 or 4', device
)
log.trace('Device %s reports itself as Unspecified', device)
ret['disks'].append(device)
return ret

View file

@ -1256,9 +1256,9 @@ def edit_team(name,
parameters = {}
if name is not None:
parameters['name'] = name
if 'description' is not None:
if description is not None:
parameters['description'] = description
if 'privacy' is not None:
if privacy is not None:
parameters['privacy'] = privacy
if permission is not None:
parameters['permission'] = permission

View file

@ -1071,7 +1071,7 @@ def remove(path, force=False):
raise SaltInvocationError('File path must be absolute: {0}'.format(path))
# Does the file/folder exists
if not os.path.exists(path):
if not os.path.exists(path) and not is_link(path):
raise CommandExecutionError('Path not found: {0}'.format(path))
# Remove ReadOnly Attribute

View file

@ -1722,16 +1722,21 @@ class Keys(LowDataAdapter):
priv_key_file = tarfile.TarInfo('minion.pem')
priv_key_file.size = len(priv_key)
fileobj = six.StringIO()
fileobj = BytesIO()
tarball = tarfile.open(fileobj=fileobj, mode='w')
tarball.addfile(pub_key_file, six.StringIO(pub_key))
tarball.addfile(priv_key_file, six.StringIO(priv_key))
if six.PY3:
pub_key = pub_key.encode(__salt_system_encoding__)
priv_key = priv_key.encode(__salt_system_encoding__)
tarball.addfile(pub_key_file, BytesIO(pub_key))
tarball.addfile(priv_key_file, BytesIO(priv_key))
tarball.close()
headers = cherrypy.response.headers
headers['Content-Disposition'] = 'attachment; filename="saltkeys-{0}.tar"'.format(lowstate[0]['id_'])
headers['Content-Type'] = 'application/x-tar'
headers['Content-Length'] = fileobj.len
headers['Content-Length'] = len(fileobj.getvalue())
headers['Cache-Control'] = 'no-cache'
fileobj.seek(0)

View file

@ -4189,7 +4189,7 @@ def replace(name,
pattern
A regular expression, to be matched using Python's
:py:func:`~re.search`.
:py:func:`re.search`.
.. note::

View file

@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Shane Lee <slee@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import textwrap
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import (
patch,
MagicMock,
NO_MOCK,
NO_MOCK_REASON
)
# Import Salt Libs
import salt.grains.disks as disks
@skipIf(NO_MOCK, NO_MOCK_REASON)
class IscsiGrainsTestCase(TestCase, LoaderModuleMockMixin):
'''
Test cases for _windows_disks grains
'''
def setup_loader_modules(self):
return {
disks: {
'__salt__': {},
},
}
def test__windows_disks(self):
'''
Test grains._windows_disks, normal return
Should return a populated dictionary
'''
mock_which = MagicMock(return_value='C:\\Windows\\System32\\wbem\\WMIC.exe')
wmic_result = textwrap.dedent('''
DeviceId MediaType
0 4
1 0
2 3
3 5
''')
mock_run_all = MagicMock(return_value={'stdout': wmic_result,
'retcode': 0})
with patch('salt.utils.path.which', mock_which), \
patch.dict(disks.__salt__, {'cmd.run_all': mock_run_all}):
result = disks._windows_disks()
expected = {
'SSDs': ['\\\\.\\PhysicalDrive0'],
'disks': [
'\\\\.\\PhysicalDrive0',
'\\\\.\\PhysicalDrive1',
'\\\\.\\PhysicalDrive2',
'\\\\.\\PhysicalDrive3']}
self.assertDictEqual(result, expected)
cmd = ' '.join([
'C:\\Windows\\System32\\wbem\\WMIC.exe',
'/namespace:\\\\root\\microsoft\\windows\\storage',
'path',
'MSFT_PhysicalDisk',
'get',
'DeviceID,MediaType',
'/format:table'
])
mock_run_all.assert_called_once_with(cmd)
def test__windows_disks_retcode(self):
'''
Test grains._windows_disks, retcode 1
Should return empty lists
'''
mock_which = MagicMock(return_value='C:\\Windows\\System32\\wbem\\WMIC.exe')
mock_run_all = MagicMock(return_value={'stdout': '',
'retcode': 1})
with patch('salt.utils.path.which', mock_which), \
patch.dict(disks.__salt__, {'cmd.run_all': mock_run_all}):
result = disks._windows_disks()
expected = {
'SSDs': [],
'disks': []}
self.assertDictEqual(result, expected)

View file

@ -19,6 +19,7 @@ from tests.support.helpers import destructiveTest
# Import Salt Libs
import salt.modules.win_file as win_file
import salt.modules.temp as temp
from salt.exceptions import CommandExecutionError
import salt.utils.platform
import salt.utils.win_functions
@ -307,3 +308,19 @@ class WinFileCheckPermsTestCase(TestCase, LoaderModuleMockMixin):
inheritance=False,
reset=True)
self.assertDictEqual(expected, ret)
def test_issue_52002_check_file_remove_symlink(self):
'''
Make sure that directories including symlinks or symlinks can be removed
'''
base = temp.dir(prefix='base')
target = os.path.join(base, 'child 1', 'target/')
symlink = os.path.join(base, 'child 2', 'link')
self.assertFalse(win_file.directory_exists(target))
self.assertFalse(win_file.directory_exists(symlink))
self.assertTrue(win_file.makedirs_(target))
self.assertTrue(win_file.directory_exists(symlink))
self.assertTrue(win_file.symlink(target, symlink))
self.assertTrue(win_file.is_link(symlink))
self.assertTrue(win_file.remove(base))
self.assertFalse(win_file.directory_exists(base))

View file

@ -69,3 +69,15 @@ class CompatTestCase(TestCase):
else:
expected = 'StringIO.StringIO instance'
self.assertTrue(expected in repr(ret))
def test_ipv6_class__is_packed_binary(self):
ipv6 = compat.IPv6AddressScoped('2001:db8::')
self.assertEqual(str(ipv6), '2001:db8::')
def test_ipv6_class__is_packed_binary_integer(self):
ipv6 = compat.IPv6AddressScoped(42540766411282592856903984951653826560)
self.assertEqual(str(ipv6), '2001:db8::')
def test_ipv6_class__is_packed_binary__issue_51831(self):
ipv6 = compat.IPv6AddressScoped(b'sixteen.digit.bn')
self.assertEqual(str(ipv6), '7369:7874:6565:6e2e:6469:6769:742e:626e')