Merge branch '2017.7' into solaris_product_grains

This commit is contained in:
Nicole Thomas 2018-05-25 09:57:40 -04:00 committed by GitHub
commit 6889befc6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 2425 additions and 136 deletions

View File

@ -2,8 +2,8 @@
source 'https://rubygems.org'
gem 'test-kitchen', '>=1.21.0'
gem 'kitchen-salt', :git => 'https://github.com/saltstack/kitchen-salt.git'
gem 'test-kitchen', '~>1.21'
gem 'kitchen-salt', '~>0.2'
gem 'kitchen-sync'
gem 'git'
@ -20,7 +20,7 @@ group :windows do
gem 'vagrant-wrapper'
gem 'kitchen-vagrant'
gem 'winrm', '~>2.0'
gem 'winrm-fs', :git => 'https://github.com/gtmanfred/winrm-fs.git'
gem 'winrm-fs', :git => 'https://github.com/WinRb/winrm-fs.git'
end
group :ec2 do

View File

@ -44,7 +44,7 @@ at ``/etc/salt/cloud.profiles`` or in the ``/etc/salt/cloud.profiles.d/`` direct
linode_1024:
provider: my-linode-config
size: Linode 2048
size: Linode 2GB
image: CentOS 7
location: London, England, UK
@ -77,12 +77,14 @@ command:
----------
linode:
----------
Linode 1024:
Linode 2GB:
----------
AVAIL:
----------
10:
500
11:
500
2:
500
3:
@ -100,11 +102,19 @@ command:
CORES:
1
DISK:
24
50
HOURLY:
0.015
LABEL:
Linode 1024
Linode 2GB
PLANID:
2
PRICE:
10.0
RAM:
2048
XFER:
2000
...SNIP...

File diff suppressed because it is too large Load Diff

165
pkg/windows/sign.bat Normal file
View File

@ -0,0 +1,165 @@
:: ############################################################################
::
:: FILE: sign.bat
::
:: DESCRIPTION: Signing and Hashing script for Salt builds on Windows.
:: Requires an official Code Signing Certificate and drivers
:: installed to sign the files. Generates hashes in MD5 and
:: SHA256 in a file of the same name with a `.md5` or
:: `.sha256` extension.
::
:: NOTE: This script is used internally by SaltStack to sign and
:: hash Windows Installer builds and uses resources not
:: available to the community, such as SaltStack's Code
:: Signing Certificate. It is placed here for version
:: control.
::
:: COPYRIGHT: (c) 2012-2018 by the SaltStack Team
::
:: LICENSE: Apache 2.0
:: ORGANIZATION: SaltStack, Inc (saltstack.com)
:: CREATED: 2017
::
:: ############################################################################
::
:: USAGE: The script must be located in a directory that has the installer
:: files in a subfolder named with the major version, ie: `2018.3`.
:: Insert the key fob that contains the code signing certificate. Run
:: the script passing the full version: `.\sign.bat 2018.3.1`.
::
:: The script will sign the installers and generate the corresponding
:: hash files. These can then be uploaded to the salt repo.
::
:: The files must be in the following format:
:: <Series>\Salt-Minion-<Version>-<Python Version>-<System Architecture>-Setup.exe
:: So, for a Salt Minion installer for 2018.3.1 on AMD64 for Python 3
:: file would be placed in a subdirectory named `2018.3` and the file
:: would be named: `Salt-Minion-2018.3.1-Py3-AMD64-Setup.exe`. This
:: is how the file is created by the NSI Script anyway.
::
:: ############################################################################
@ echo off
if [%1]==[] (
echo You must pass a version
goto quit
) else (
set "Version=%~1"
)
for /F "tokens=1,2 delims=." %%a in ("%Version%") do (set Series=%%a.%%b)
:: Sign Installer Files
echo ===========================================================================
echo Signing...
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
signtool.exe sign /t http://timestamp.digicert.com ^
"%Series%\Salt-Minion-%Version%-AMD64-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-x86-Setup.exe" ^
"%Series%\Salt-%Version%-AMD64-Setup.exe" ^
"%Series%\Salt-%Version%-x86-Setup.exe" ^
"%Series%\Salt-%Version%-Py2-AMD64-Setup.exe" ^
"%Series%\Salt-%Version%-Py2-x86-Setup.exe" ^
"%Series%\Salt-%Version%-Py3-AMD64-Setup.exe" ^
"%Series%\Salt-%Version%-Py3-x86-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py2-AMD64-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py2-x86-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py3-AMD64-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py3-x86-Setup.exe"
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Signing Complete
echo ===========================================================================
:: Create Hash files
echo ===========================================================================
echo Creating Hashes...
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set "file_name=Salt-Minion-%Version%-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py2-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py2-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py3-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py3-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py2-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py2-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py3-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py3-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Hashing Complete
echo ===========================================================================
:quit

View File

@ -5,6 +5,6 @@ msgpack>=0.5,!=0.5.5
PyYAML
MarkupSafe
requests>=1.0.0
tornado>=4.2.1,<5.0
tornado>=4.2.1,<6.0
# Required by Tornado to handle threads stuff.
futures>=2.0; python_version < '3.0'

View File

@ -255,7 +255,7 @@ def file_hash(load, fnd):
except OSError:
pass
return file_hash(load, fnd)
if os.path.getmtime(path) == mtime:
if str(os.path.getmtime(path)) == mtime:
# check if mtime changed
ret['hsum'] = hsum
return ret

View File

@ -1841,6 +1841,13 @@ class Minion(MinionBase):
self.schedule.functions = self.functions
self.schedule.returners = self.returners
def beacons_refresh(self):
'''
Refresh the functions and returners.
'''
log.debug('Refreshing beacons.')
self.beacons = salt.beacons.Beacon(self.opts, self.functions)
# TODO: only allow one future in flight at a time?
@tornado.gen.coroutine
def pillar_refresh(self, force_refresh=False):
@ -2007,6 +2014,8 @@ class Minion(MinionBase):
yield self.pillar_refresh(
force_refresh=data.get('force_refresh', False)
)
elif tag.startswith('beacons_refresh'):
self.beacons_refresh()
elif tag.startswith('manage_schedule'):
self.manage_schedule(tag, data)
elif tag.startswith('manage_beacons'):

View File

@ -640,6 +640,10 @@ def disassociate_vpc_from_hosted_zone(HostedZoneId=None, Name=None, VPCId=None,
r = conn.disassociate_vpc_from_hosted_zone(**args)
return _wait_for_sync(r['ChangeInfo']['Id'], conn)
except ClientError as e:
if e.response.get('Error', {}).get('Code') == 'VPCAssociationNotFound':
log.debug('No VPC Association exists.')
# return True since the current state is the desired one
return True
if tries and e.response.get('Error', {}).get('Code') == 'Throttling':
log.debug('Throttled by AWS API.')
time.sleep(3)

View File

@ -476,6 +476,9 @@ def authorize(name=None, source_group_name=None,
log.error(msg)
return False
except boto.exception.EC2ResponseError as e:
# if we are trying to add the same rule then we are already in the desired state, return true
if e.error_code == 'InvalidPermission.Duplicate':
return True
msg = ('Failed to add rule to security group {0} with id {1}.'
.format(group.name, group.id))
log.error(msg)

View File

@ -510,7 +510,7 @@ def get_system_info():
.. code-block:: bash
salt 'minion-id' system.get_info
salt 'minion-id' system.get_system_info
'''
os_type = {1: 'Work Station',
2: 'Domain Controller',

View File

@ -85,6 +85,7 @@ def _strip_headers(output, *args):
if not args:
args_lc = ('installed packages',
'available packages',
'available upgrades',
'updated packages',
'upgraded packages')
else:

View File

@ -829,7 +829,7 @@ def _get_configured_repos():
'''
repos_cfg = configparser.ConfigParser()
repos_cfg.read([REPOS + '/' + fname for fname in os.listdir(REPOS)])
repos_cfg.read([REPOS + '/' + fname for fname in os.listdir(REPOS) if fname.endswith(".repo")])
return repos_cfg

View File

@ -7,6 +7,8 @@ for managing outputters.
# Import python libs
from __future__ import print_function
from __future__ import absolute_import
import io
import re
import os
import sys
@ -169,7 +171,7 @@ def get_printout(out, opts=None, **kwargs):
'''
try:
fileno = sys.stdout.fileno()
except AttributeError:
except (AttributeError, io.UnsupportedOperation):
fileno = -1 # sys.stdout is StringIO or fake
return not os.isatty(fileno)

View File

@ -243,11 +243,21 @@ def find_sls_ids(sls, high):
'''
ret = []
for nid, item in six.iteritems(high):
if item['__sls__'] == sls:
for st_ in item:
if st_.startswith('__'):
continue
ret.append((nid, st_))
try:
sls_tgt = item['__sls__']
except TypeError:
if nid != '__exclude__':
log.error(
'Invalid non-dict item \'%s\' in high data. Value: %r',
nid, item
)
continue
else:
if sls_tgt == sls:
for st_ in item:
if st_.startswith('__'):
continue
ret.append((nid, st_))
return ret

View File

@ -2449,13 +2449,21 @@ def latest(
'result': None,
'comment': '\n'.join(comments)}
# Build updated list of pkgs to exclude non-targeted ones
targeted_pkgs = list(targets.keys()) if pkgs else None
if salt.utils.is_windows():
# pkg.install execution module on windows ensures the software
# package is installed when no version is specified, it does not
# upgrade the software to the latest. This is per the design.
# Build updated list of pkgs *with verion number*, exclude
# non-targeted ones
targeted_pkgs = [{x: targets[x]} for x in targets]
else:
# Build updated list of pkgs to exclude non-targeted ones
targeted_pkgs = list(targets)
# No need to refresh, if a refresh was necessary it would have been
# performed above when pkg.latest_version was run.
try:
# No need to refresh, if a refresh was necessary it would have been
# performed above when pkg.latest_version was run.
changes = __salt__['pkg.install'](name,
changes = __salt__['pkg.install'](name=None,
refresh=False,
fromrepo=fromrepo,
skip_verify=skip_verify,

View File

@ -196,16 +196,17 @@ def present(name, properties=None, filesystem_properties=None, layout=None, conf
# figure out if updates needed
properties_update = []
for prop in properties:
if prop not in properties_current:
continue
if properties:
for prop in properties:
if prop not in properties_current:
continue
value = properties[prop]
if isinstance(value, bool):
value = 'on' if value else 'off'
value = properties[prop]
if isinstance(value, bool):
value = 'on' if value else 'off'
if properties_current[prop] != value:
properties_update.append(prop)
if properties_current[prop] != value:
properties_update.append(prop)
# update properties
for prop in properties_update:

View File

@ -593,23 +593,22 @@ class TCPReqServerChannel(salt.transport.mixins.auth.AESReqServerMixin, salt.tra
self.payload_handler = payload_handler
self.io_loop = io_loop
self.serial = salt.payload.Serial(self.opts)
if USE_LOAD_BALANCER:
self.req_server = LoadBalancerWorker(self.socket_queue,
self.handle_message,
io_loop=self.io_loop,
ssl_options=self.opts.get('ssl'))
else:
if salt.utils.is_windows():
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
_set_tcp_keepalive(self._socket, self.opts)
self._socket.setblocking(0)
self._socket.bind((self.opts['interface'], int(self.opts['ret_port'])))
self.req_server = SaltMessageServer(self.handle_message,
io_loop=self.io_loop,
ssl_options=self.opts.get('ssl'))
self.req_server.add_socket(self._socket)
self._socket.listen(self.backlog)
with salt.utils.async.current_ioloop(self.io_loop):
if USE_LOAD_BALANCER:
self.req_server = LoadBalancerWorker(self.socket_queue,
self.handle_message,
ssl_options=self.opts.get('ssl'))
else:
if salt.utils.is_windows():
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
_set_tcp_keepalive(self._socket, self.opts)
self._socket.setblocking(0)
self._socket.bind((self.opts['interface'], int(self.opts['ret_port'])))
self.req_server = SaltMessageServer(self.handle_message,
ssl_options=self.opts.get('ssl'))
self.req_server.add_socket(self._socket)
self._socket.listen(self.backlog)
salt.transport.mixins.auth.AESReqServerMixin.post_fork(self, payload_handler, io_loop)
@tornado.gen.coroutine
@ -694,6 +693,7 @@ class SaltMessageServer(tornado.tcpserver.TCPServer, object):
'''
def __init__(self, message_handler, *args, **kwargs):
super(SaltMessageServer, self).__init__(*args, **kwargs)
self.io_loop = tornado.ioloop.IOLoop.current()
self.clients = []
self.message_handler = message_handler
@ -797,7 +797,9 @@ class TCPClientKeepAlive(tornado.tcpclient.TCPClient):
stream = tornado.iostream.IOStream(
sock,
max_buffer_size=max_buffer_size)
return stream.connect(addr)
if tornado.version_info < (5,):
return stream.connect(addr)
return stream, stream.connect(addr)
class SaltMessageClientPool(salt.transport.MessageClientPool):
@ -878,33 +880,33 @@ class SaltMessageClient(object):
return
self._closing = True
if hasattr(self, '_stream') and not self._stream.closed():
self._stream.close()
if self._read_until_future is not None:
# This will prevent this message from showing up:
# '[ERROR ] Future exception was never retrieved:
# StreamClosedError'
# This happens because the logic is always waiting to read
# the next message and the associated read future is marked
# 'StreamClosedError' when the stream is closed.
self._read_until_future.exception()
if (not self._stream_return_future.done() and
self.io_loop != tornado.ioloop.IOLoop.current(
instance=False)):
# If _stream_return() hasn't completed, it means the IO
# Loop is stopped (such as when using
# 'salt.utils.async.SyncWrapper'). Ensure that
# _stream_return() completes by restarting the IO Loop.
# This will prevent potential errors on shutdown.
orig_loop = tornado.ioloop.IOLoop.current()
self.io_loop.make_current()
try:
# If _stream_return() hasn't completed, it means the IO
# Loop is stopped (such as when using
# 'salt.utils.async.SyncWrapper'). Ensure that
# _stream_return() completes by restarting the IO Loop.
# This will prevent potential errors on shutdown.
try:
orig_loop = tornado.ioloop.IOLoop.current()
self.io_loop.make_current()
self._stream.close()
if self._read_until_future is not None:
# This will prevent this message from showing up:
# '[ERROR ] Future exception was never retrieved:
# StreamClosedError'
# This happens because the logic is always waiting to read
# the next message and the associated read future is marked
# 'StreamClosedError' when the stream is closed.
self._read_until_future.exception()
if (not self._stream_return_future.done() and
self.io_loop != tornado.ioloop.IOLoop.current(
instance=False)):
self.io_loop.add_future(
self._stream_return_future,
lambda future: self.io_loop.stop()
)
self.io_loop.start()
finally:
orig_loop.make_current()
finally:
orig_loop.make_current()
self._tcp_client.close()
# Clear callback references to allow the object that they belong to
# to be deleted.

View File

@ -18,11 +18,12 @@ import salt.utils
from tests.support.case import ShellCase
from tests.support.paths import FILES
from tests.support.helpers import expensiveTest
from tests.support.unit import expectedFailure
from tests.support.unit import expectedFailure, skipIf
from tests.support import win_installer
# Import Third-Party Libs
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
import salt.utils.cloud
def __random_name(size=6):
@ -37,13 +38,14 @@ def __random_name(size=6):
# Create the cloud instance name to be used throughout the tests
INSTANCE_NAME = __random_name()
PROVIDER_NAME = 'ec2'
HAS_WINRM = salt.utils.cloud.HAS_WINRM and salt.utils.cloud.HAS_SMB
TIMEOUT = 1200
class EC2Test(ShellCase):
'''
Integration tests for the EC2 cloud provider in Salt-Cloud
'''
TIMEOUT = 500
def _installer_name(self):
'''
@ -185,17 +187,17 @@ class EC2Test(ShellCase):
'''
# create the instance
rename = INSTANCE_NAME + '-rename'
instance = self.run_cloud('-p ec2-test {0} --no-deploy'.format(INSTANCE_NAME), timeout=500)
instance = self.run_cloud('-p ec2-test {0} --no-deploy'.format(INSTANCE_NAME), timeout=TIMEOUT)
ret_str = '{0}:'.format(INSTANCE_NAME)
# check if instance returned
try:
self.assertIn(ret_str, instance)
except AssertionError:
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=500)
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=TIMEOUT)
raise
change_name = self.run_cloud('-a rename {0} newname={1} --assume-yes'.format(INSTANCE_NAME, rename), timeout=500)
change_name = self.run_cloud('-a rename {0} newname={1} --assume-yes'.format(INSTANCE_NAME, rename), timeout=TIMEOUT)
check_rename = self.run_cloud('-a show_instance {0} --assume-yes'.format(rename), [rename])
exp_results = [' {0}:'.format(rename), ' size:',
@ -204,11 +206,11 @@ class EC2Test(ShellCase):
for result in exp_results:
self.assertIn(result, check_rename[0])
except AssertionError:
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=500)
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=TIMEOUT)
raise
# delete the instance
delete = self.run_cloud('-d {0} --assume-yes'.format(rename), timeout=500)
delete = self.run_cloud('-d {0} --assume-yes'.format(rename), timeout=TIMEOUT)
ret_str = ' shutting-down'
# check if deletion was performed appropriately
@ -236,8 +238,9 @@ class EC2Test(ShellCase):
'win_installer': self.copy_file(self.INSTALLER),
},
)
self._test_instance('ec2-win2012r2-test', debug=True, timeout=500)
self._test_instance('ec2-win2012r2-test', debug=True, timeout=TIMEOUT)
@skipIf(not HAS_WINRM, 'Skip when winrm dependencies are missing')
def test_win2012r2_winrm(self):
'''
Tests creating and deleting a Windows 2012r2 instance on EC2 using
@ -249,10 +252,11 @@ class EC2Test(ShellCase):
'userdata_file': self.copy_file('windows-firewall.ps1'),
'win_installer': self.copy_file(self.INSTALLER),
'winrm_ssl_verify': False,
'use_winrm': True,
}
)
self._test_instance('ec2-win2012r2-test', debug=True, timeout=500)
self._test_instance('ec2-win2012r2-test', debug=True, timeout=TIMEOUT)
@expectedFailure
def test_win2016_winexe(self):
@ -270,8 +274,9 @@ class EC2Test(ShellCase):
'win_installer': self.copy_file(self.INSTALLER),
},
)
self._test_instance('ec2-win2016-test', debug=True, timeout=500)
self._test_instance('ec2-win2016-test', debug=True, timeout=TIMEOUT)
@skipIf(not HAS_WINRM, 'Skip when winrm dependencies are missing')
def test_win2016_winrm(self):
'''
Tests creating and deleting a Windows 2016 instance on EC2 using winrm
@ -283,10 +288,11 @@ class EC2Test(ShellCase):
'userdata_file': self.copy_file('windows-firewall.ps1'),
'win_installer': self.copy_file(self.INSTALLER),
'winrm_ssl_verify': False,
'use_winrm': True,
}
)
self._test_instance('ec2-win2016-test', debug=True, timeout=500)
self._test_instance('ec2-win2016-test', debug=True, timeout=TIMEOUT)
def tearDown(self):
'''
@ -297,4 +303,4 @@ class EC2Test(ShellCase):
# if test instance is still present, delete it
if ret_str in query:
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=self.TIMEOUT)
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=TIMEOUT)

View File

@ -1,12 +1,12 @@
ec2-test:
provider: ec2-config
image: ami-98aa1cf0
size: t1.micro
size: m1.large
sh_username: ec2-user
script_args: '-P -Z'
ec2-win2012r2-test:
provider: ec2-config
size: t2.micro
size: m1.large
image: ami-eb1ecd96
smb_port: 445
win_installer: ''
@ -16,11 +16,10 @@ ec2-win2012r2-test:
userdata_template: False
use_winrm: True
winrm_verify_ssl: False
ssh_interface: private_ips
deploy: True
ec2-win2016-test:
provider: ec2-config
size: t2.micro
size: m1.large
image: ami-ed14c790
smb_port: 445
win_installer: ''
@ -30,5 +29,4 @@ ec2-win2016-test:
userdata_template: False
use_winrm: True
winrm_verify_ssl: False
ssh_interface: private_ips
deploy: True

View File

@ -1,5 +1,5 @@
linode-test:
provider: linode-config
size: Linode 2048
size: Linode 2GB
image: Ubuntu 14.04 LTS
script_args: '-P -Z'

View File

@ -0,0 +1,2 @@
slsfile1-nop:
test.nop

View File

@ -0,0 +1,2 @@
slsfile2-nop:
test.nop

View File

@ -0,0 +1,2 @@
include:
- issue-47182.stateA.newer

View File

@ -0,0 +1,6 @@
exclude:
- sls: issue-47182.stateA
somestuff:
cmd.run:
- name: echo This supersedes the stuff previously done in issue-47182.stateA

View File

@ -0,0 +1,10 @@
include:
- issue-47182.slsfile1
- issue-47182.slsfile2
some-state:
test.nop:
- require:
- sls: issue-47182.slsfile1
- require_in:
- sls: issue-47182.slsfile2

View File

@ -0,0 +1,4 @@
base:
'*':
- issue-47182.stateA
- issue-47182.stateB

View File

@ -12,7 +12,8 @@ from tests.support.case import ModuleCase
from tests.support.helpers import (
destructiveTest,
skip_if_binaries_missing,
skip_if_not_root
skip_if_not_root,
this_user,
)
from tests.support.paths import TMP
@ -227,12 +228,7 @@ class CMDModuleTest(ModuleCase):
cmd = '''echo 'SELECT * FROM foo WHERE bar="baz"' '''
expected_result = 'SELECT * FROM foo WHERE bar="baz"'
try:
runas = os.getlogin()
except: # pylint: disable=W0702
# On some distros (notably Gentoo) os.getlogin() fails
import pwd
runas = pwd.getpwuid(os.getuid())[0]
runas = this_user()
result = self.run_function('cmd.run_stdout', [cmd],
runas=runas).strip()

View File

@ -16,6 +16,7 @@ from tests.support.helpers import destructiveTest, skip_if_not_root
# Import Salt Libs
import salt.utils
from salt.exceptions import CommandExecutionError
import salt.ext.six as six
# Import 3rd-party libs
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
@ -173,8 +174,11 @@ class MacUserModuleTest(ModuleCase):
self.assertTrue(os.path.exists('/etc/kcpassword'))
# Are the contents of the file correct
test_data = b".\xc3\xb8'B\xc2\xa0\xc3\x99\xc2\xad\xc2\x8b\xc3\x8d\xc3\x8dl"
with salt.utils.fopen('/etc/kcpassword', 'rb') as f:
if six.PY2:
test_data = b'.\xf8\'B\xa0\xd9\xad\x8b\xcd\xcdl'
else:
test_data = b".\xc3\xb8'B\xc2\xa0\xc3\x99\xc2\xad\xc2\x8b\xc3\x8d\xc3\x8dl"
with salt.utils.fopen('/etc/kcpassword', 'r' if six.PY2 else 'rb') as f:
file_data = f.read()
self.assertEqual(test_data, file_data)

View File

@ -11,7 +11,6 @@ from __future__ import absolute_import
import os
import re
import shutil
import sys
import tempfile
# Import Salt Testing libs
@ -73,8 +72,7 @@ class PipModuleTest(ModuleCase):
# Let's remove the pip binary
pip_bin = os.path.join(self.venv_dir, 'bin', 'pip')
py_dir = 'python{0}.{1}'.format(*sys.version_info[:2])
site_dir = os.path.join(self.venv_dir, 'lib', py_dir, 'site-packages')
site_dir = self.run_function('virtualenv.get_distribution_path', [self.venv_dir, 'pip'])
if salt.utils.is_windows():
pip_bin = os.path.join(self.venv_dir, 'Scripts', 'pip.exe')
site_dir = os.path.join(self.venv_dir, 'lib', 'site-packages')

View File

@ -337,23 +337,34 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
self.assertNotEqual(ret['changes'], {})
@destructiveTest
@skipIf(salt.utils.is_windows(), 'minion is windows')
@skipIf(salt.utils.is_darwin(), 'minion is mac')
def test_pkg_latest_version(self):
'''
check that pkg.latest_version returns the latest version of the uninstalled package (it does not install the package, just checking the version)
'''
grains = self.run_function('grains.items')
cmd_info = self.run_function('pkg.info_installed', ['htop'])
if cmd_info != 'ERROR: package htop is not installed':
cmd_remove = self.run_function('pkg.remove', ['htop'])
remove = False
if salt.utils.is_windows():
cmd_info = self.run_function('pkg.version', [self.pkg])
remove = False if cmd_info == '' else True
else:
cmd_info = self.run_function('pkg.info_installed', [self.pkg])
if cmd_info != 'ERROR: package {0} is not installed'.format(self.pkg):
remove = True
# remove package if its installed
if remove:
cmd_remove = self.run_function('pkg.remove', [self.pkg])
if grains['os_family'] == 'RedHat':
cmd_htop = self.run_function('cmd.run', ['yum list htop'])
cmd_pkg = self.run_function('cmd.run', ['yum list {0}'.format(self.pkg)])
elif salt.utils.is_windows():
cmd_pkg = self.run_function('pkg.list_available', [self.pkg])
elif grains['os_family'] == 'Debian':
cmd_htop = self.run_function('cmd.run', ['apt list htop'])
cmd_pkg = self.run_function('cmd.run', ['apt list {0}'.format(self.pkg)])
elif grains['os_family'] == 'Arch':
cmd_htop = self.run_function('cmd.run', ['pacman -Si htop'])
cmd_pkg = self.run_function('cmd.run', ['pacman -Si {0}'.format(self.pkg)])
elif grains['os_family'] == 'Suse':
cmd_htop = self.run_function('cmd.run', ['zypper info htop'])
pkg_latest = self.run_function('pkg.latest_version', ['htop'])
self.assertIn(pkg_latest, cmd_htop)
cmd_pkg = self.run_function('cmd.run', ['zypper info {0}'.format(self.pkg)])
pkg_latest = self.run_function('pkg.latest_version', [self.pkg])
self.assertIn(pkg_latest, cmd_pkg)

View File

@ -118,7 +118,7 @@ class ServiceModuleTest(ModuleCase):
systemd = salt.utils.systemd.booted()
# check service was not enabled
if systemd:
if systemd or salt.utils.is_windows():
self.assertIn('ERROR', enable)
else:
self.assertFalse(enable)

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.unit import skipIf
# Import Salt libs
import salt.utils
@skipIf(not salt.utils.is_windows(), 'windows test only')
class WinServermanagerTest(ModuleCase):
'''
Test for salt.modules.win_servermanager
'''
def test_list_available(self):
'''
Test list available features to install
'''
cmd = self.run_function('win_servermanager.list_available')
self.assertIn('DNS', cmd)
self.assertIn('NetworkController', cmd)
self.assertIn('RemoteAccess', cmd)

View File

@ -236,8 +236,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
# Let's remove the pip binary
pip_bin = os.path.join(venv_dir, 'bin', 'pip')
py_dir = 'python{0}.{1}'.format(*sys.version_info[:2])
site_dir = os.path.join(venv_dir, 'lib', py_dir, 'site-packages')
site_dir = self.run_function('virtualenv.get_distribution_path', [venv_dir, 'pip'])
if salt.utils.is_windows():
pip_bin = os.path.join(venv_dir, 'Scripts', 'pip.exe')
site_dir = os.path.join(venv_dir, 'lib', 'site-packages')

View File

@ -44,12 +44,6 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin):
user_name = 'salt_test'
user_home = '/var/lib/salt_test'
def setUp(self):
if salt.utils.is_darwin():
#on mac we need to add user, because there is
#no creationtime for nobody user.
add_user = self.run_function('user.add', [USER], gid=GID)
def test_user_absent(self):
ret = self.run_state('user.absent', name='unpossible')
self.assertSaltTrueReturn(ret)

View File

@ -34,6 +34,7 @@ import types
# Import 3rd-party libs
import psutil # pylint: disable=3rd-party-module-not-gated
import salt.ext.six as six
import salt.utils
from salt.ext.six.moves import range, builtins # pylint: disable=import-error,redefined-builtin
try:
from pytestsalt.utils import get_unused_localhost_port # pylint: disable=unused-import
@ -52,6 +53,10 @@ except ImportError:
from tests.support.unit import skip, _id
from tests.support.mock import patch
from tests.support.paths import FILES, TMP
if salt.utils.is_windows():
import salt.utils.win_functions
else:
import pwd
# Import Salt libs
import salt.utils
@ -1138,7 +1143,6 @@ def skip_if_not_root(func):
func.__unittest_skip__ = True
func.__unittest_skip_why__ = 'You must be logged in as root to run this test'
else:
import salt.utils.win_functions
current_user = salt.utils.win_functions.get_current_user()
if current_user != 'SYSTEM':
if not salt.utils.win_functions.is_admin(current_user):
@ -1552,3 +1556,12 @@ def win32_kill_process_tree(pid, sig=signal.SIGTERM, include_parent=True,
gone, alive = psutil.wait_procs(children, timeout=timeout,
callback=on_terminate)
return (gone, alive)
def this_user():
'''
Get the user associated with the current process.
'''
if salt.utils.is_windows():
return salt.utils.win_functions.get_current_user()
return pwd.getpwuid(os.getuid())[0]

View File

@ -48,6 +48,8 @@ SYS_TMP_DIR = os.path.abspath(os.path.realpath(
))
TMP = os.path.join(SYS_TMP_DIR, 'salt-tests-tmpdir')
FILES = os.path.join(INTEGRATION_TEST_DIR, 'files')
BASE_FILES = os.path.join(FILES, 'file', 'base')
PROD_FILES = os.path.join(FILES, 'file', 'prod')
PYEXEC = 'python{0}.{1}'.format(*sys.version_info)
MOCKBIN = os.path.join(INTEGRATION_TEST_DIR, 'mockbin')
SCRIPT_DIR = os.path.join(CODE_DIR, 'scripts')

View File

@ -49,7 +49,6 @@
# Import Python modules
from __future__ import absolute_import, print_function
import os
import sys
import json
import shutil
import logging
@ -57,6 +56,7 @@ import multiprocessing
# Import tests support libs
import tests.support.paths as paths
import tests.support.helpers
# Import 3rd-party libs
import salt.ext.six as six
@ -103,12 +103,9 @@ try:
except ImportError:
pass
if sys.platform.startswith('win'):
import win32api # pylint: disable=import-error
RUNNING_TESTS_USER = win32api.GetUserName()
else:
import pwd
RUNNING_TESTS_USER = pwd.getpwuid(os.getuid()).pw_name
RUNNING_TESTS_USER = tests.support.helpers.this_user()
log = logging.getLogger(__name__)

View File

@ -12,7 +12,7 @@ import textwrap
import logging
import stat
try:
import pwd
import pwd # pylint: disable=unused-import
except ImportError:
pass
@ -31,6 +31,7 @@ from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import NO_MOCK, NO_MOCK_REASON
from tests.support.paths import TMP, FILES
from tests.support.helpers import this_user
# Import salt libs
import salt.utils.gitfs
@ -207,11 +208,7 @@ class GitFSTest(TestCase, LoaderModuleMockMixin):
if 'USERNAME' not in os.environ:
try:
import salt.utils
if salt.utils.is_windows():
import salt.utils.win_functions
os.environ['USERNAME'] = salt.utils.win_functions.get_current_user()
else:
os.environ['USERNAME'] = pwd.getpwuid(os.geteuid()).pw_name
os.environ['USERNAME'] = this_user()
except AttributeError:
log.error('Unable to get effective username, falling back to '
'\'root\'.')

View File

@ -220,6 +220,7 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
self.assertRaises(CommandExecutionError, cmdmod._run, 'foo')
@skipIf(salt.utils.is_windows(), 'Do not run on Windows')
@skipIf(True, 'Test breaks unittests runs')
def test_run(self):
'''
Tests end result when a command is not found

View File

@ -7,6 +7,7 @@
from __future__ import absolute_import
import copy
import os
import shutil
import tempfile
# Import Salt Testing libs
@ -14,6 +15,7 @@ import tests.integration as integration
from tests.support.unit import TestCase, skipIf
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, patch
from tests.support.mixins import AdaptedConfigurationTestCaseMixin
from tests.support.paths import BASE_FILES
# Import Salt libs
import salt.state
@ -66,9 +68,9 @@ class StateCompilerTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
class HighStateTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
def setUp(self):
root_dir = tempfile.mkdtemp(dir=integration.TMP)
state_tree_dir = os.path.join(root_dir, 'state_tree')
self.state_tree_dir = os.path.join(root_dir, 'state_tree')
cache_dir = os.path.join(root_dir, 'cachedir')
for dpath in (root_dir, state_tree_dir, cache_dir):
for dpath in (root_dir, self.state_tree_dir, cache_dir):
if not os.path.isdir(dpath):
os.makedirs(dpath)
@ -77,7 +79,7 @@ class HighStateTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
overrides['state_events'] = False
overrides['id'] = 'match'
overrides['file_client'] = 'local'
overrides['file_roots'] = dict(base=[state_tree_dir])
overrides['file_roots'] = dict(base=[self.state_tree_dir])
overrides['cachedir'] = cache_dir
overrides['test'] = False
self.config = self.get_temp_config('minion', **overrides)
@ -138,6 +140,28 @@ class HighStateTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
self.assertEqual(state_usage_dict['base']['used'], ['state.a', 'state.b'])
self.assertEqual(state_usage_dict['base']['unused'], ['state.c'])
def test_find_sls_ids_with_exclude(self):
'''
See https://github.com/saltstack/salt/issues/47182
'''
sls_dir = 'issue-47182'
shutil.copytree(
os.path.join(BASE_FILES, sls_dir),
os.path.join(self.state_tree_dir, sls_dir)
)
shutil.move(
os.path.join(self.state_tree_dir, sls_dir, 'top.sls'),
self.state_tree_dir
)
# Manually compile the high data. We don't have to worry about all of
# the normal error checking we do here since we know that all the SLS
# files exist and there is no whitelist/blacklist being used.
top = self.highstate.get_top() # pylint: disable=assignment-from-none
matches = self.highstate.top_matches(top)
high, _ = self.highstate.render_highstate(matches)
ret = salt.state.find_sls_ids('issue-47182.stateA.newer', high)
self.assertEqual(ret, [('somestuff', 'cmd')])
class TopFileMergeTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
'''