Merge branch '2017.7' into bugfix-grain-virtual_subtype

This commit is contained in:
Nicole Thomas 2018-04-03 15:39:43 -04:00 committed by GitHub
commit 9eb6f5c0d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 531 additions and 145 deletions

View file

@ -250,9 +250,9 @@ on_saltstack = 'SALT_ON_SALTSTACK' in os.environ
project = 'Salt'
version = salt.version.__version__
latest_release = '2017.7.4' # latest release
previous_release = '2016.11.9' # latest release from previous branch
previous_release_dir = '2016.11' # path on web server for previous branch
latest_release = '2018.3.0' # latest release
previous_release = '2017.7.5' # latest release from previous branch
previous_release_dir = '2017.7' # path on web server for previous branch
next_release = '' # next release
next_release_dir = '' # path on web server for next release branch
@ -263,8 +263,8 @@ if on_saltstack:
copyright = time.strftime("%Y")
# < --- START do not merge these settings to other branches START ---> #
build_type = 'latest' # latest, previous, develop, next
release = latest_release # version, latest_release, previous_release
build_type = 'previous' # latest, previous, develop, next
release = previous_release # version, latest_release, previous_release
# < --- END do not merge these settings to other branches END ---> #
# Set google custom search engine

View file

@ -37,8 +37,8 @@ import logging
log = logging.getLogger(__name__)
def auth(username, sharedsecret, **kwargs):
def auth(username, password):
'''
Shared secret authentication
'''
return sharedsecret == __opts__.get('sharedsecret')
return password == __opts__.get('sharedsecret')

View file

@ -2336,6 +2336,9 @@ def wait_for_instance(
use_winrm = config.get_cloud_config_value(
'use_winrm', vm_, __opts__, default=False
)
winrm_verify_ssl = config.get_cloud_config_value(
'winrm_verify_ssl', vm_, __opts__, default=True
)
if win_passwd and win_passwd == 'auto':
log.debug('Waiting for auto-generated Windows EC2 password')
@ -2407,7 +2410,8 @@ def wait_for_instance(
winrm_port,
username,
win_passwd,
timeout=ssh_connect_timeout):
timeout=ssh_connect_timeout,
verify=winrm_verify_ssl):
raise SaltCloudSystemExit(
'Failed to authenticate against remote windows host'
)

View file

@ -14,6 +14,7 @@ import logging
import inspect
import tempfile
import functools
import threading
import types
from collections import MutableMapping
from zipimport import zipimporter
@ -1100,7 +1101,8 @@ class LazyLoader(salt.utils.lazy.LazyDict):
self.disabled = set(self.opts.get('disable_{0}{1}'.format(
self.tag, '' if self.tag[-1] == 's' else 's'), []))
self.refresh_file_mapping()
self._lock = threading.RLock()
self._refresh_file_mapping()
super(LazyLoader, self).__init__() # late init the lazy loader
# create all of the import namespaces
@ -1167,7 +1169,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
else:
return '\'{0}\' __virtual__ returned False'.format(mod_name)
def refresh_file_mapping(self):
def _refresh_file_mapping(self):
'''
refresh the mapping of the FS on disk
'''
@ -1285,15 +1287,16 @@ class LazyLoader(salt.utils.lazy.LazyDict):
'''
Clear the dict
'''
super(LazyLoader, self).clear() # clear the lazy loader
self.loaded_files = set()
self.missing_modules = {}
self.loaded_modules = {}
# if we have been loaded before, lets clear the file mapping since
# we obviously want a re-do
if hasattr(self, 'opts'):
self.refresh_file_mapping()
self.initial_load = False
with self._lock:
super(LazyLoader, self).clear() # clear the lazy loader
self.loaded_files = set()
self.missing_modules = {}
self.loaded_modules = {}
# if we have been loaded before, lets clear the file mapping since
# we obviously want a re-do
if hasattr(self, 'opts'):
self._refresh_file_mapping()
self.initial_load = False
def __prep_mod_opts(self, opts):
'''
@ -1504,14 +1507,14 @@ class LazyLoader(salt.utils.lazy.LazyDict):
virtual_funcs_to_process = ['__virtual__'] + self.virtual_funcs
for virtual_func in virtual_funcs_to_process:
virtual_ret, module_name, virtual_err, virtual_aliases = \
self.process_virtual(mod, module_name)
self._process_virtual(mod, module_name)
if virtual_err is not None:
log.trace(
'Error loading %s.%s: %s',
self.tag, module_name, virtual_err
)
# if process_virtual returned a non-True value then we are
# if _process_virtual returned a non-True value then we are
# supposed to not process this module
if virtual_ret is not True and module_name not in self.missing_modules:
# If a module has information about why it could not be loaded, record it
@ -1601,39 +1604,42 @@ class LazyLoader(salt.utils.lazy.LazyDict):
if not isinstance(key, six.string_types) or '.' not in key:
raise KeyError
mod_name, _ = key.split('.', 1)
if mod_name in self.missing_modules:
return True
# if the modulename isn't in the whitelist, don't bother
if self.whitelist and mod_name not in self.whitelist:
raise KeyError
with self._lock:
# It is possible that the key is in the dictionary after
# acquiring the lock due to another thread loading it.
if mod_name in self.missing_modules or key in self._dict:
return True
# if the modulename isn't in the whitelist, don't bother
if self.whitelist and mod_name not in self.whitelist:
raise KeyError
def _inner_load(mod_name):
for name in self._iter_files(mod_name):
if name in self.loaded_files:
continue
# if we got what we wanted, we are done
if self._load_module(name) and key in self._dict:
return True
return False
def _inner_load(mod_name):
for name in self._iter_files(mod_name):
if name in self.loaded_files:
continue
# if we got what we wanted, we are done
if self._load_module(name) and key in self._dict:
return True
return False
# try to load the module
ret = None
reloaded = False
# re-scan up to once, IOErrors or a failed load cause re-scans of the
# filesystem
while True:
try:
ret = _inner_load(mod_name)
if not reloaded and ret is not True:
self.refresh_file_mapping()
reloaded = True
# try to load the module
ret = None
reloaded = False
# re-scan up to once, IOErrors or a failed load cause re-scans of the
# filesystem
while True:
try:
ret = _inner_load(mod_name)
if not reloaded and ret is not True:
self._refresh_file_mapping()
reloaded = True
continue
break
except IOError:
if not reloaded:
self._refresh_file_mapping()
reloaded = True
continue
break
except IOError:
if not reloaded:
self.refresh_file_mapping()
reloaded = True
continue
return ret
@ -1641,16 +1647,18 @@ class LazyLoader(salt.utils.lazy.LazyDict):
'''
Load all of them
'''
for name in self.file_mapping:
if name in self.loaded_files or name in self.missing_modules:
continue
self._load_module(name)
with self._lock:
for name in self.file_mapping:
if name in self.loaded_files or name in self.missing_modules:
continue
self._load_module(name)
self.loaded = True
self.loaded = True
def reload_modules(self):
self.loaded_files = set()
self._load_all()
with self._lock:
self.loaded_files = set()
self._load_all()
def _apply_outputter(self, func, mod):
'''
@ -1661,7 +1669,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
if func.__name__ in outp:
func.__outputter__ = outp[func.__name__]
def process_virtual(self, mod, module_name, virtual_func='__virtual__'):
def _process_virtual(self, mod, module_name, virtual_func='__virtual__'):
'''
Given a loaded module and its default name determine its virtual name

View file

@ -3038,6 +3038,7 @@ def rm_(name, force=False, volumes=False, **kwargs):
'''
kwargs = salt.utils.clean_kwargs(**kwargs)
stop_ = kwargs.pop('stop', False)
auto_remove = False
if kwargs:
salt.utils.invalid_kwargs(kwargs)
@ -3047,9 +3048,19 @@ def rm_(name, force=False, volumes=False, **kwargs):
'remove this container'.format(name)
)
if stop_ and not force:
inspect_results = inspect_container(name)
try:
auto_remove = inspect_results['HostConfig']['AutoRemove']
except KeyError:
log.error(
'Failed to find AutoRemove in inspect results, Docker API may '
'have changed. Full results: %s', inspect_results
)
stop(name)
pre = ps_(all=True)
_client_wrapper('remove_container', name, v=volumes, force=force)
if not auto_remove:
_client_wrapper('remove_container', name, v=volumes, force=force)
_clear_context()
return [x for x in pre if x not in ps_(all=True)]

View file

@ -25,7 +25,6 @@ import logging
try:
from sense_hat import SenseHat
_sensehat = SenseHat()
has_sense_hat = True
except (ImportError, NameError):
_sensehat = None
@ -39,14 +38,19 @@ def __virtual__():
Only load the module if SenseHat is available
'''
if has_sense_hat:
try:
_sensehat = SenseHat()
except OSError:
return False, 'This module can only be used on a Raspberry Pi with a SenseHat.'
rotation = __salt__['pillar.get']('sensehat:rotation', 0)
if rotation in [0, 90, 180, 270]:
_sensehat.set_rotation(rotation, False)
else:
log.error("{0} is not a valid rotation. Using default rotation.".format(rotation))
log.error('{0} is not a valid rotation. Using default rotation.'.format(rotation))
return True
else:
return False, "The SenseHat excecution module can not be loaded: SenseHat unavailable.\nThis module can only be used on a Raspberry Pi with a SenseHat. Also make sure that the sense_hat python library is installed!"
return False, 'The SenseHat execution module cannot be loaded: \'sense_hat\' python library unavailable.'
def set_pixels(pixels):

View file

@ -2030,8 +2030,9 @@ def event(tagmatch='*',
indent=None if not pretty else 4)))
sys.stdout.flush()
count -= 1
log.debug('Remaining event matches: %s', count)
if count > 0:
count -= 1
log.debug('Remaining event matches: %s', count)
if count == 0:
break

View file

@ -3439,7 +3439,7 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
element_valuenames = []
element_values = this_element_value
if this_element_value is not None:
element_valuenames = list(range(1, len(this_element_value) + 1))
element_valuenames = list([str(z) for z in range(1, len(this_element_value) + 1)])
if 'additive' in element.attrib:
if element.attrib['additive'].lower() == 'false':
# a delete values will be added before all the other
@ -3464,11 +3464,18 @@ def _processValueItem(element, reg_key, reg_valuename, policy, parent_element,
if this_element_value is not None:
element_valuenames = this_element_value.keys()
element_values = this_element_value.values()
if 'valuePrefix' in element.attrib and element.attrib['valuePrefix'] != '':
if this_element_value is not None:
element_valuenames = ['{0}{1}'.format(element.attrib['valuePrefix'],
k) for k in element_valuenames]
if 'valuePrefix' in element.attrib:
# if the valuePrefix attribute exists, the valuenames are <prefix><number>
# most prefixes attributes are empty in the admx files, so the valuenames
# end up being just numbers
if element.attrib['valuePrefix'] != '':
if this_element_value is not None:
element_valuenames = ['{0}{1}'.format(element.attrib['valuePrefix'],
k) for k in element_valuenames]
else:
# if there is no valuePrefix attribute, the valuename is the value
if element_values is not None:
element_valuenames = [str(z) for z in element_values]
if not check_deleted:
if this_element_value is not None:
log.debug('_processValueItem has an explicit element_value of {0}'.format(this_element_value))

View file

@ -2582,7 +2582,8 @@ def mod_repo(repo, basedir=None, **kwargs):
# Build a list of keys to be deleted
todelete = []
for key in repo_opts:
# list() of keys because the dict could be shrinking in the for loop.
for key in list(repo_opts):
if repo_opts[key] != 0 and not repo_opts[key]:
del repo_opts[key]
todelete.append(key)

View file

@ -265,8 +265,13 @@ def managed(name,
ret['comment'] = ' '.join(errors)
return ret
try:
currently_enabled = __salt__['ip.is_enabled'](name)
except CommandExecutionError:
currently_enabled = False
if not enabled:
if __salt__['ip.is_enabled'](name):
if currently_enabled:
if __opts__['test']:
ret['result'] = None
ret['comment'] = ('Interface \'{0}\' will be disabled'
@ -280,18 +285,13 @@ def managed(name,
ret['comment'] += ' (already disabled)'
return ret
else:
try:
currently_enabled = __salt__['ip.is_disabled'](name)
except CommandExecutionError:
currently_enabled = False
if not currently_enabled:
if __opts__['test']:
ret['result'] = None
ret['comment'] = ('Interface \'{0}\' will be enabled'
.format(name))
else:
result = __salt__['ip.enable'](name)
if not result:
if not __salt__['ip.enable'](name):
ret['result'] = False
ret['comment'] = ('Failed to enable interface \'{0}\' to '
'make changes'.format(name))

View file

@ -515,7 +515,10 @@ def bootstrap(vm_, opts=None):
'winrm_port', vm_, opts, default=5986
)
deploy_kwargs['winrm_use_ssl'] = salt.config.get_cloud_config_value(
'winrm_use_ssl', vm_, opts, default=True
'winrm_use_ssl', vm_, opts, default=True
)
deploy_kwargs['winrm_verify_ssl'] = salt.config.get_cloud_config_value(
'winrm_verify_ssl', vm_, opts, default=True
)
if saltify_driver:
deploy_kwargs['port_timeout'] = 1 # No need to wait/retry with Saltify
@ -843,7 +846,7 @@ def wait_for_winexesvc(host, port, username, password, timeout=900):
time.sleep(1)
def wait_for_winrm(host, port, username, password, timeout=900, use_ssl=True):
def wait_for_winrm(host, port, username, password, timeout=900, use_ssl=True, verify=True):
'''
Wait until WinRM connection can be established.
'''
@ -853,14 +856,20 @@ def wait_for_winrm(host, port, username, password, timeout=900, use_ssl=True):
host, port
)
)
transport = 'ssl'
if not use_ssl:
transport = 'plaintext'
trycount = 0
while True:
trycount += 1
try:
transport = 'ssl'
if not use_ssl:
transport = 'plaintext'
s = winrm.Session(host, auth=(username, password), transport=transport)
winrm_kwargs = {'target': host,
'auth': (username, password),
'transport': transport}
if not verify:
log.debug("SSL validation for WinRM disabled.")
winrm_kwargs['server_cert_validation'] = 'ignore'
s = winrm.Session(**winrm_kwargs)
if hasattr(s.protocol, 'set_timeout'):
s.protocol.set_timeout(15)
log.trace('WinRM endpoint url: {0}'.format(s.url))
@ -1008,6 +1017,7 @@ def deploy_windows(host,
use_winrm=False,
winrm_port=5986,
winrm_use_ssl=True,
winrm_verify_ssl=True,
**kwargs):
'''
Copy the install files to a remote Windows box, and execute them
@ -1034,7 +1044,8 @@ def deploy_windows(host,
if HAS_WINRM and use_winrm:
winrm_session = wait_for_winrm(host=host, port=winrm_port,
username=username, password=password,
timeout=port_timeout * 60, use_ssl=winrm_use_ssl)
timeout=port_timeout * 60, use_ssl=winrm_use_ssl,
verify=winrm_verify_ssl)
if winrm_session is not None:
service_available = True
else:

View file

@ -35,6 +35,7 @@ import salt.utils.args
import salt.utils.xdg
import salt.utils.jid
import salt.utils.files
import salt.utils.win_functions
from salt.utils import kinds
from salt.defaults import DEFAULT_TARGET_DELIM
from salt.utils.validate.path import is_writeable
@ -1017,11 +1018,11 @@ class DaemonMixIn(six.with_metaclass(MixInMeta, object)):
if self.check_pidfile():
pid = self.get_pidfile()
if not salt.utils.is_windows():
if self.check_pidfile() and self.is_daemonized(pid) and not os.getppid() == pid:
if self.check_pidfile() and self.is_daemonized(pid) and os.getppid() != pid:
return True
else:
# We have no os.getppid() on Windows. Best effort.
if self.check_pidfile() and self.is_daemonized(pid):
# We have no os.getppid() on Windows. Use salt.utils.win_functions.get_parent_pid
if self.check_pidfile() and self.is_daemonized(pid) and salt.utils.win_functions.get_parent_pid() != pid:
return True
return False

View file

@ -147,7 +147,7 @@ def get_pidfile(pidfile):
pid = pdf.read().strip()
return int(pid)
except (OSError, IOError, TypeError, ValueError):
return None
return -1
def clean_proc(proc, wait_for_kill=10):

View file

@ -8,14 +8,18 @@ from __future__ import absolute_import
import os
import random
import string
import yaml
# Import Salt Libs
from salt.config import cloud_providers_config
import salt.utils
# Import Salt Testing Libs
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 import win_installer
# Import Third-Party Libs
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
@ -39,6 +43,38 @@ class EC2Test(ShellCase):
'''
Integration tests for the EC2 cloud provider in Salt-Cloud
'''
TIMEOUT = 500
def _installer_name(self):
'''
Determine the downloaded installer name by searching the files
directory for the firt file that loosk like an installer.
'''
for path, dirs, files in os.walk(FILES):
for file in files:
if file.startswith(win_installer.PREFIX):
return file
break
return
def _fetch_latest_installer(self):
'''
Download the latest Windows installer executable
'''
name = win_installer.latest_installer_name()
path = os.path.join(FILES, name)
with salt.utils.fopen(path, 'wb') as fp:
win_installer.download_and_verify(fp, name)
return name
def _ensure_installer(self):
'''
Make sure the testing environment has a Windows installer executbale.
'''
name = self._installer_name()
if name:
return name
return self._fetch_latest_installer()
@expensiveTest
def setUp(self):
@ -90,24 +126,51 @@ class EC2Test(ShellCase):
'missing. Check tests/integration/files/conf/cloud.providers.d/{0}.conf'
.format(PROVIDER_NAME)
)
self.INSTALLER = self._ensure_installer()
def test_instance(self):
def override_profile_config(self, name, data):
conf_path = os.path.join(self.get_config_dir(), 'cloud.profiles.d', 'ec2.conf')
with salt.utils.fopen(conf_path, 'r') as fp:
conf = yaml.safe_load(fp)
conf[name].update(data)
with salt.utils.fopen(conf_path, 'w') as fp:
yaml.dump(conf, fp)
def copy_file(self, name):
'''
Copy a file from tests/integration/files to a test's temporary
configuration directory. The path to the file which is created will be
returned.
'''
src = os.path.join(FILES, name)
dst = os.path.join(self.get_config_dir(), name)
with salt.utils.fopen(src, 'rb') as sfp:
with salt.utils.fopen(dst, 'wb') as dfp:
dfp.write(sfp.read())
return dst
def _test_instance(self, profile='ec2-test', debug=False, timeout=TIMEOUT):
'''
Tests creating and deleting an instance on EC2 (classic)
'''
# create the instance
instance = self.run_cloud('-p ec2-test {0}'.format(INSTANCE_NAME), timeout=500)
cmd = '-p {0}'.format(profile)
if debug:
cmd += ' -l debug'
cmd += ' {0}'.format(INSTANCE_NAME)
instance = self.run_cloud(cmd, timeout=timeout)
ret_str = '{0}:'.format(INSTANCE_NAME)
# check if instance returned with salt installed
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
# delete the instance
delete = self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=500)
delete = self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=timeout)
ret_str = ' shutting-down'
# check if deletion was performed appropriately
@ -151,6 +214,80 @@ class EC2Test(ShellCase):
# check if deletion was performed appropriately
self.assertIn(ret_str, delete)
def test_instance(self):
'''
Tests creating and deleting an instance on EC2 (classic)
'''
self._test_instance('ec2-test')
@expectedFailure
def test_win2012r2_winexe(self):
'''
Tests creating and deleting a Windows 2012r2instance on EC2 using
winexe (classic)
'''
# TODO: winexe calls hang and the test fails by timing out. The same
# same calls succeed when run outside of the test environment.
self.override_profile_config(
'ec2-win2012-test',
{
'use_winrm': False,
'user_data': self.copy_file('windows-firewall-winexe.ps1'),
'win_installer': self.copy_file(self.INSTALLER),
},
)
self._test_instance('ec2-win2012r2-test', debug=True, timeout=500)
def test_win2012r2_winrm(self):
'''
Tests creating and deleting a Windows 2012r2 instance on EC2 using
winrm (classic)
'''
self.override_profile_config(
'ec2-win2016-test',
{
'user_data': self.copy_file('windows-firewall.ps1'),
'win_installer': self.copy_file(self.INSTALLER),
'winrm_ssl_verify': False,
}
)
self._test_instance('ec2-win2012r2-test', debug=True, timeout=500)
@expectedFailure
def test_win2016_winexe(self):
'''
Tests creating and deleting a Windows 2016 instance on EC2 using winrm
(classic)
'''
# TODO: winexe calls hang and the test fails by timing out. The same
# same calls succeed when run outside of the test environment.
self.override_profile_config(
'ec2-win2016-test',
{
'use_winrm': False,
'user_data': self.copy_file('windows-firewall-winexe.ps1'),
'win_installer': self.copy_file(self.INSTALLER),
},
)
self._test_instance('ec2-win2016-test', debug=True, timeout=500)
def test_win2016_winrm(self):
'''
Tests creating and deleting a Windows 2016 instance on EC2 using winrm
(classic)
'''
self.override_profile_config(
'ec2-win2016-test',
{
'user_data': self.copy_file('windows-firewall.ps1'),
'win_installer': self.copy_file(self.INSTALLER),
'winrm_ssl_verify': False,
}
)
self._test_instance('ec2-win2016-test', debug=True, timeout=500)
def tearDown(self):
'''
Clean up after tests
@ -160,4 +297,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=500)
self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=self.TIMEOUT)

View file

@ -4,3 +4,31 @@ ec2-test:
size: t1.micro
sh_username: ec2-user
script_args: '-P -Z'
ec2-win2012r2-test:
provider: ec2-config
size: t2.micro
image: ami-eb1ecd96
smb_port: 445
win_installer: ''
win_username: Administrator
win_password: auto
userdata_file: ''
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
image: ami-ed14c790
smb_port: 445
win_installer: ''
win_username: Administrator
win_password: auto
userdata_file: ''
userdata_template: False
use_winrm: True
winrm_verify_ssl: False
ssh_interface: private_ips
deploy: True

View file

@ -63,6 +63,8 @@ def get_invalid_docs():
'log.warning',
'lowpkg.bin_pkg_info',
'lxc.run_cmd',
'mantest.install',
'mantest.search',
'nspawn.restart',
'nspawn.stop',
'pkg.expand_repo_def',

View file

@ -0,0 +1,5 @@
<powershell>
New-NetFirewallRule -Name "SMB445" -DisplayName "SMB445" -Protocol TCP -LocalPort 445
Set-Item (dir wsman:\localhost\Listener\*\Port -Recurse).pspath 445 -Force
Restart-Service winrm
</powershell>

View file

@ -0,0 +1,33 @@
<powershell>
New-NetFirewallRule -Name "SMB445" -DisplayName "SMB445" -Protocol TCP -LocalPort 445
New-NetFirewallRule -Name "WINRM5986" -DisplayName "WINRM5986" -Protocol TCP -LocalPort 5986
winrm quickconfig -q
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}'
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
$SourceStoreScope = 'LocalMachine'
$SourceStorename = 'Remote Desktop'
$SourceStore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $SourceStorename, $SourceStoreScope
$SourceStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
$cert = $SourceStore.Certificates | Where-Object -FilterScript {
$_.subject -like '*'
}
$DestStoreScope = 'LocalMachine'
$DestStoreName = 'My'
$DestStore = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $DestStoreName, $DestStoreScope
$DestStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
$DestStore.Add($cert)
$SourceStore.Close()
$DestStore.Close()
winrm create winrm/config/listener?Address=*+Transport=HTTPS `@`{Hostname=`"($certId)`"`;CertificateThumbprint=`"($cert.Thumbprint)`"`}
Restart-Service winrm
</powershell>

View file

@ -84,7 +84,8 @@ class SaltUtilSyncModuleTest(ModuleCase):
'beacons': [],
'utils': [],
'returners': [],
'modules': ['modules.override_test',
'modules': ['modules.mantest',
'modules.override_test',
'modules.runtests_decorators',
'modules.runtests_helpers',
'modules.salttest'],
@ -127,7 +128,8 @@ class SaltUtilSyncModuleTest(ModuleCase):
'beacons': [],
'utils': [],
'returners': [],
'modules': ['modules.override_test',
'modules': ['modules.mantest',
'modules.override_test',
'modules.runtests_helpers',
'modules.salttest'],
'renderers': [],

View file

@ -33,7 +33,7 @@ class NpmStateTest(ModuleCase, SaltReturnAssertsMixin):
Basic test to determine if NPM module was successfully installed and
removed.
'''
ret = self.run_state('npm.installed', name='pm2')
ret = self.run_state('npm.installed', name='pm2', registry="http://registry.npmjs.org/")
self.assertSaltTrueReturn(ret)
ret = self.run_state('npm.removed', name='pm2')
self.assertSaltTrueReturn(ret)
@ -51,7 +51,11 @@ class NpmStateTest(ModuleCase, SaltReturnAssertsMixin):
else:
user = None
npm_dir = None
ret = self.run_state('npm.installed', name='request/request#v2.81.1', runas=user, dir=npm_dir)
ret = self.run_state('npm.installed',
name='request/request#v2.81.1',
runas=user,
dir=npm_dir,
registry="http://registry.npmjs.org/")
self.assertSaltTrueReturn(ret)
ret = self.run_state('npm.removed', name='git://github.com/request/request', runas=user, dir=npm_dir)
self.assertSaltTrueReturn(ret)
@ -65,7 +69,7 @@ class NpmStateTest(ModuleCase, SaltReturnAssertsMixin):
Basic test to determine if NPM module successfully installs multiple
packages.
'''
ret = self.run_state('npm.installed', name=None, pkgs=['pm2', 'grunt'])
ret = self.run_state('npm.installed', name=None, pkgs=['pm2', 'grunt'], registry="http://registry.npmjs.org/")
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.which('npm') and LooseVersion(cmd.run('npm -v')) >= LooseVersion(MAX_NPM_VERSION),

View file

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
'''
:copyright: Copyright 2013-2017 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.
tests.support.win_installer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fetches the binary Windows installer
'''
from __future__ import absolute_import
import hashlib
import requests
import re
PREFIX = 'Salt-Minion-'
REPO = "https://repo.saltstack.com/windows"
def iter_installers(content):
'''
Parse a list of windows installer links and their corresponding md5
checksum links.
'''
HREF_RE = "<a href=\"(.*?)\">"
installer, md5 = None, None
for m in re.finditer(HREF_RE, content):
x = m.groups()[0]
if not x.startswith(PREFIX):
continue
if x.endswith('zip'):
continue
if installer:
if x != installer + '.md5':
raise Exception("Unable to parse response")
md5 = x
yield installer, md5
installer, md5 = None, None
else:
installer = x
def split_installer(name):
'''
Return a tuple of the salt version, python verison and architecture from an
installer name.
'''
x = name[len(PREFIX):]
return x.split('-')[:3]
def latest_version(repo=REPO):
'''
Return the latest version found on the salt repository webpage.
'''
for name, md5 in iter_installers(requests.get(repo).content):
pass
return split_installer(name)[0]
def installer_name(salt_ver, py_ver='Py2', arch='AMD64'):
'''
Create an installer file name
'''
return "Salt-Minion-{}-{}-{}-Setup.exe".format(salt_ver, py_ver, arch)
def latest_installer_name(repo=REPO, **kwargs):
'''
Fetch the latest installer name
'''
return installer_name(latest_version(repo), **kwargs)
def download_and_verify(fp, name, repo=REPO):
'''
Download an installer and verify it's contents.
'''
md5 = "{}.md5".format(name)
url = lambda x: "{}/{}".format(repo, x)
resp = requests.get(url(md5))
if resp.status_code != 200:
raise Exception("Unable to fetch installer md5")
installer_md5 = resp.text.strip().split()[0].lower()
resp = requests.get(url(name), stream=True)
if resp.status_code != 200:
raise Exception("Unable to fetch installer")
md5hsh = hashlib.md5()
for chunk in resp.iter_content(chunk_size=1024):
md5hsh.update(chunk)
fp.write(chunk)
if md5hsh.hexdigest() != installer_md5:
raise Exception("Installer's hash does not match {} != {}".format(
md5hsh.hexdigest(), installer_md5
))

View file

@ -19,6 +19,8 @@
# Import Python Libs
from __future__ import absolute_import
import os
import errno
import subprocess
# Import Salt Testing Libs
from tests.support.unit import TestCase, skipIf
@ -33,7 +35,33 @@ from tests.support.mock import (
from salt.modules.inspectlib.collector import Inspector
HAS_SYMLINKS = None
def no_symlinks():
'''
Check if git is installed and has symlinks enabled in the configuration.
'''
global HAS_SYMLINKS
if HAS_SYMLINKS is not None:
return not HAS_SYMLINKS
output = ''
try:
output = subprocess.check_output('git config --get core.symlinks', shell=True)
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
except subprocess.CalledProcessError:
# git returned non-zero status
pass
HAS_SYMLINKS = False
if output.strip() == 'true':
HAS_SYMLINKS = True
return not HAS_SYMLINKS
@skipIf(NO_MOCK, NO_MOCK_REASON)
@skipIf(no_symlinks(), "Git missing 'core.symlinks=true' config")
class InspectorCollectorTestCase(TestCase):
'''
Test inspectlib:collector:Inspector

View file

@ -41,17 +41,18 @@ class WinNetworkTestCase(TestCase, LoaderModuleMockMixin):
' static, dhcp.'})
self.assertDictEqual(win_network.managed('salt'), ret)
mock = MagicMock(return_value=False)
mock_false = MagicMock(return_value=False)
mock_true = MagicMock(return_value=True)
mock1 = MagicMock(side_effect=[False, True, True, True, True, True,
True])
mock2 = MagicMock(side_effect=[False, True, True, {'salt': 'True'},
{'salt': 'True'}])
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock,
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock_false,
"ip.is_disabled": mock1,
"ip.enable": mock,
"ip.enable": mock_false,
"ip.get_interface": mock2,
"ip.set_dhcp_dns": mock,
"ip.set_dhcp_ip": mock}):
"ip.set_dhcp_dns": mock_false,
"ip.set_dhcp_ip": mock_false}):
ret.update({'comment': "Interface 'salt' is up to date."
" (already disabled)", 'result': True})
self.assertDictEqual(win_network.managed('salt',
@ -66,52 +67,54 @@ class WinNetworkTestCase(TestCase, LoaderModuleMockMixin):
dns_proto='static',
ip_proto='static'),
ret)
mock = MagicMock(side_effect=['True', False, False, False, False,
mock_false = MagicMock(side_effect=['True', False, False, False, False,
False])
with patch.object(win_network, '_validate', mock):
ret.update({'comment': 'The following SLS configuration'
' errors were detected: T r u e'})
self.assertDictEqual(win_network.managed('salt',
dns_proto='static',
ip_proto='static'),
ret)
ret.update({'comment': "Unable to get current"
" configuration for interface 'salt'",
'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='dhcp',
ip_proto='dhcp'),
ret)
with patch.dict(win_network.__salt__, {"ip.is_enabled": mock_true}):
with patch.object(win_network, '_validate', mock_false):
ret.update({'comment': 'The following SLS configuration'
' errors were detected: T r u e'})
self.assertDictEqual(win_network.managed('salt',
dns_proto='static',
ip_proto='static'),
ret)
mock = MagicMock(side_effect=[False, [''],
{'dns_proto': 'dhcp',
'ip_proto': 'dhcp'},
{'dns_proto': 'dhcp',
'ip_proto': 'dhcp'}])
ret.update({'comment': "Interface 'salt' is up to date.",
'result': True})
with patch.object(win_network, '_changes', mock):
ret.update({'comment': "Unable to get current"
" configuration for interface 'salt'",
'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='dhcp',
ip_proto='dhcp'
), ret)
ip_proto='dhcp'),
ret)
ret.update({'comment': "The following changes will be made"
" to interface 'salt': ", 'result': None})
with patch.dict(win_network.__opts__, {"test": True}):
mock_false = MagicMock(side_effect=[False, [''],
{'dns_proto': 'dhcp',
'ip_proto': 'dhcp'},
{'dns_proto': 'dhcp',
'ip_proto': 'dhcp'}])
ret.update({'comment': "Interface 'salt' is up to date.",
'result': True})
with patch.object(win_network, '_changes', mock_false):
self.assertDictEqual(win_network.managed('salt',
dns_proto='dh'
'cp',
dns_proto='dhcp',
ip_proto='dhcp'
), ret)
with patch.dict(win_network.__opts__, {"test": False}):
ret.update({'comment': "Failed to set desired"
" configuration settings for interface"
" 'salt'", 'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='dh'
'cp',
ip_proto='dhcp'
), ret)
ret.update({'comment': "The following changes will be made"
" to interface 'salt': ", 'result': None})
with patch.dict(win_network.__opts__, {"test": True}):
self.assertDictEqual(win_network.managed('salt',
dns_proto='dh'
'cp',
ip_proto='dhcp'
), ret)
with patch.dict(win_network.__opts__, {"test": False}):
ret.update({'comment': "Failed to set desired"
" configuration settings for interface"
" 'salt'", 'result': False})
self.assertDictEqual(win_network.managed('salt',
dns_proto='dh'
'cp',
ip_proto='dhcp'
), ret)