mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #49282 from rallytime/merge-2018.3
[2018.3] Merge forward from 2017.7 to 2018.3
This commit is contained in:
commit
914bb09667
24 changed files with 369 additions and 242 deletions
|
@ -125,7 +125,7 @@
|
|||
# The master can take a while to start up when lspci and/or dmidecode is used
|
||||
# to populate the grains for the master. Enable if you want to see GPU hardware
|
||||
# data for your master.
|
||||
# enable_gpu_grains: False
|
||||
# enable_gpu_grains: True
|
||||
|
||||
# The master maintains a job cache. While this is a great addition, it can be
|
||||
# a burden on the master for larger deployments (over 5000 minions).
|
||||
|
@ -574,12 +574,6 @@
|
|||
#
|
||||
#master_tops: {}
|
||||
|
||||
# The external_nodes option allows Salt to gather data that would normally be
|
||||
# placed in a top file. The external_nodes option is the executable that will
|
||||
# return the ENC data. Remember that Salt will look for external nodes AND top
|
||||
# files and combine the results if both are enabled!
|
||||
#external_nodes: None
|
||||
|
||||
# The renderer to use on the minions to render the state data
|
||||
#renderer: yaml_jinja
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ syndic_user: salt
|
|||
# The master can take a while to start up when lspci and/or dmidecode is used
|
||||
# to populate the grains for the master. Enable if you want to see GPU hardware
|
||||
# data for your master.
|
||||
# enable_gpu_grains: False
|
||||
# enable_gpu_grains: True
|
||||
|
||||
# The master maintains a job cache. While this is a great addition, it can be
|
||||
# a burden on the master for larger deployments (over 5000 minions).
|
||||
|
@ -536,12 +536,6 @@ syndic_user: salt
|
|||
#
|
||||
#master_tops: {}
|
||||
|
||||
# The external_nodes option allows Salt to gather data that would normally be
|
||||
# placed in a top file. The external_nodes option is the executable that will
|
||||
# return the ENC data. Remember that Salt will look for external nodes AND top
|
||||
# files and combine the results if both are enabled!
|
||||
#external_nodes: None
|
||||
|
||||
# The renderer to use on the minions to render the state data
|
||||
#renderer: yaml_jinja
|
||||
|
||||
|
|
|
@ -5256,7 +5256,7 @@ sock_dir: /var/run/salt/master
|
|||
.UNINDENT
|
||||
.SS \fBenable_gpu_grains\fP
|
||||
.sp
|
||||
Default: \fBTrue\fP
|
||||
Default: \fBFalse\fP
|
||||
.sp
|
||||
Enable GPU hardware data for your master. Be aware that the master can
|
||||
take a while to start up when lspci and/or dmidecode is used to populate the
|
||||
|
@ -6993,25 +6993,6 @@ master_tops:
|
|||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS \fBexternal_nodes\fP
|
||||
.sp
|
||||
Default: None
|
||||
.sp
|
||||
The external_nodes option allows Salt to gather data that would normally be
|
||||
placed in a top file from and external node controller. The external_nodes
|
||||
option is the executable that will return the ENC data. Remember that Salt
|
||||
will look for external nodes AND top files and combine the results if both
|
||||
are enabled and available!
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
external_nodes: cobbler\-ext\-nodes
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS \fBrenderer\fP
|
||||
.sp
|
||||
Default: \fByaml_jinja\fP
|
||||
|
@ -15229,7 +15210,7 @@ and \fBmine_functions\fP\&.
|
|||
# The master can take a while to start up when lspci and/or dmidecode is used
|
||||
# to populate the grains for the master. Enable if you want to see GPU hardware
|
||||
# data for your master.
|
||||
# enable_gpu_grains: False
|
||||
# enable_gpu_grains: True
|
||||
|
||||
# The master maintains a job cache. While this is a great addition, it can be
|
||||
# a burden on the master for larger deployments (over 5000 minions).
|
||||
|
@ -15678,12 +15659,6 @@ and \fBmine_functions\fP\&.
|
|||
#
|
||||
#master_tops: {}
|
||||
|
||||
# The external_nodes option allows Salt to gather data that would normally be
|
||||
# placed in a top file. The external_nodes option is the executable that will
|
||||
# return the ENC data. Remember that Salt will look for external nodes AND top
|
||||
# files and combine the results if both are enabled!
|
||||
#external_nodes: None
|
||||
|
||||
# The renderer to use on the minions to render the state data
|
||||
#renderer: yaml_jinja
|
||||
|
||||
|
|
|
@ -472,7 +472,7 @@ communication.
|
|||
``enable_gpu_grains``
|
||||
---------------------
|
||||
|
||||
Default: ``True``
|
||||
Default: ``False``
|
||||
|
||||
Enable GPU hardware data for your master. Be aware that the master can
|
||||
take a while to start up when lspci and/or dmidecode is used to populate the
|
||||
|
@ -2059,23 +2059,6 @@ following configuration:
|
|||
master_tops:
|
||||
ext_nodes: <Shell command which returns yaml>
|
||||
|
||||
.. conf_master:: external_nodes
|
||||
|
||||
``external_nodes``
|
||||
------------------
|
||||
|
||||
Default: None
|
||||
|
||||
The external_nodes option allows Salt to gather data that would normally be
|
||||
placed in a top file from and external node controller. The external_nodes
|
||||
option is the executable that will return the ENC data. Remember that Salt
|
||||
will look for external nodes AND top files and combine the results if both
|
||||
are enabled and available!
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
external_nodes: cobbler-ext-nodes
|
||||
|
||||
.. conf_master:: renderer
|
||||
|
||||
``renderer``
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#======================================================================================================================
|
||||
set -o nounset # Treat unset variables as an error
|
||||
|
||||
__ScriptVersion="2018.08.13"
|
||||
__ScriptVersion="2018.08.15"
|
||||
__ScriptName="bootstrap-salt.sh"
|
||||
|
||||
__ScriptFullName="$0"
|
||||
|
@ -3140,7 +3140,7 @@ install_debian_8_git_deps() {
|
|||
|
||||
__PACKAGES="libzmq3 libzmq3-dev lsb-release python-apt python-crypto python-jinja2"
|
||||
__PACKAGES="${__PACKAGES} python-m2crypto python-msgpack python-requests python-systemd"
|
||||
__PACKAGES="${__PACKAGES} python-yaml python-zmq"
|
||||
__PACKAGES="${__PACKAGES} python-yaml python-zmq python-concurrent.futures"
|
||||
|
||||
if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
|
||||
# Install python-libcloud if asked to
|
||||
|
@ -3211,7 +3211,7 @@ install_debian_9_git_deps() {
|
|||
PY_PKG_VER=""
|
||||
|
||||
# These packages are PY2-ONLY
|
||||
__PACKAGES="${__PACKAGES} python-backports-abc python-m2crypto"
|
||||
__PACKAGES="${__PACKAGES} python-backports-abc python-m2crypto python-concurrent.futures"
|
||||
fi
|
||||
|
||||
__PACKAGES="${__PACKAGES} python${PY_PKG_VER}-apt python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
|
||||
|
@ -3429,7 +3429,7 @@ install_fedora_deps() {
|
|||
fi
|
||||
fi
|
||||
|
||||
__PACKAGES="${__PACKAGES} dnf-utils libyaml python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
|
||||
__PACKAGES="${__PACKAGES} procps-ng dnf-utils libyaml python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
|
||||
__PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-requests python${PY_PKG_VER}-zmq"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
|
@ -3800,7 +3800,7 @@ install_centos_git_deps() {
|
|||
fi
|
||||
fi
|
||||
|
||||
__PACKAGES="python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
|
||||
__PACKAGES="${__PACKAGES} python${PY_PKG_VER}-crypto python${PY_PKG_VER}-jinja2"
|
||||
__PACKAGES="${__PACKAGES} python${PY_PKG_VER}-msgpack python${PY_PKG_VER}-requests"
|
||||
__PACKAGES="${__PACKAGES} python${PY_PKG_VER}-tornado python${PY_PKG_VER}-zmq"
|
||||
|
||||
|
@ -3815,7 +3815,7 @@ install_centos_git_deps() {
|
|||
|
||||
if [ "${_PY_EXE}" != "" ] && [ "$_PIP_ALLOWED" -eq "$BS_TRUE" ]; then
|
||||
# If "-x" is defined, install dependencies with pip based on the Python version given.
|
||||
_PIP_PACKAGES="m2crypto jinja2 msgpack-python pycrypto PyYAML tornado<5.0 zmq"
|
||||
_PIP_PACKAGES="m2crypto jinja2 msgpack-python pycrypto PyYAML tornado<5.0 zmq futures>=2.0"
|
||||
|
||||
# install swig and openssl on cent6
|
||||
if [ "$DISTRO_MAJOR_VERSION" -eq 6 ]; then
|
||||
|
@ -4608,6 +4608,7 @@ _eof
|
|||
# which is already installed
|
||||
__PACKAGES="m2crypto ${pkg_append}-crypto ${pkg_append}-jinja2 ${pkg_append}-PyYAML"
|
||||
__PACKAGES="${__PACKAGES} ${pkg_append}-msgpack ${pkg_append}-requests ${pkg_append}-zmq"
|
||||
__PACKAGES="${__PACKAGES} ${pkg_append}-futures"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
__yum_install_noinput ${__PACKAGES} || return 1
|
||||
|
@ -4627,6 +4628,9 @@ install_amazon_linux_ami_git_deps() {
|
|||
PIP_EXE='pip'
|
||||
if __check_command_exists python2.7; then
|
||||
if ! __check_command_exists pip2.7; then
|
||||
if ! __check_command_exists easy_install-2.7; then
|
||||
__yum_install_noinput python27-setuptools
|
||||
fi
|
||||
/usr/bin/easy_install-2.7 pip || return 1
|
||||
fi
|
||||
PIP_EXE='/usr/local/bin/pip2.7'
|
||||
|
@ -4646,7 +4650,7 @@ install_amazon_linux_ami_git_deps() {
|
|||
|
||||
if [ "$_INSTALL_CLOUD" -eq $BS_TRUE ]; then
|
||||
__check_pip_allowed "You need to allow pip based installations (-P) in order to install apache-libcloud"
|
||||
__PACKAGES="${__PACKAGES} python-pip"
|
||||
__PACKAGES="${__PACKAGES} python27-pip"
|
||||
__PIP_PACKAGES="${__PIP_PACKAGES} apache-libcloud>=$_LIBCLOUD_MIN_VERSION"
|
||||
fi
|
||||
|
||||
|
@ -4795,7 +4799,7 @@ install_arch_linux_stable() {
|
|||
pacman -S --noconfirm --needed bash || return 1
|
||||
pacman -Su --noconfirm || return 1
|
||||
# We can now resume regular salt update
|
||||
pacman -Syu --noconfirm salt || return 1
|
||||
pacman -Syu --noconfirm salt python2-futures || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -5649,7 +5653,7 @@ install_opensuse_git_deps() {
|
|||
|
||||
__git_clone_and_checkout || return 1
|
||||
|
||||
__PACKAGES="libzmq5 python-Jinja2 python-m2crypto python-msgpack-python python-pycrypto python-pyzmq python-xml"
|
||||
__PACKAGES="libzmq5 python-Jinja2 python-m2crypto python-msgpack-python python-pycrypto python-pyzmq python-xml python-futures"
|
||||
|
||||
if [ -f "${_SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" ]; then
|
||||
# We're on the develop branch, install whichever tornado is on the requirements file
|
||||
|
|
|
@ -1212,9 +1212,17 @@ class SAuth(AsyncAuth):
|
|||
creds = self.sign_in(channel=channel)
|
||||
if creds == 'retry':
|
||||
if self.opts.get('caller'):
|
||||
print('Minion failed to authenticate with the master, '
|
||||
'has the minion key been accepted?')
|
||||
sys.exit(2)
|
||||
# We have a list of masters, so we should break
|
||||
# and try the next one in the list.
|
||||
if self.opts.get('local_masters', None):
|
||||
error = SaltClientError('Minion failed to authenticate'
|
||||
' with the master, has the '
|
||||
'minion key been accepted?')
|
||||
break
|
||||
else:
|
||||
print('Minion failed to authenticate with the master, '
|
||||
'has the minion key been accepted?')
|
||||
sys.exit(2)
|
||||
if acceptance_wait_time:
|
||||
log.info('Waiting %s seconds before retry.', acceptance_wait_time)
|
||||
time.sleep(acceptance_wait_time)
|
||||
|
|
|
@ -530,7 +530,7 @@ def name(device, partition, name):
|
|||
'Invalid characters passed to partition.name'
|
||||
)
|
||||
|
||||
cmd = 'parted -m -s {0} name {1} {2}'.format(device, partition, name)
|
||||
cmd = '''parted -m -s {0} name {1} "'{2}'"'''.format(device, partition, name)
|
||||
out = __salt__['cmd.run'](cmd).splitlines()
|
||||
return out
|
||||
|
||||
|
|
|
@ -88,8 +88,6 @@ SERVICE_ERROR_CONTROL = {0: 'Ignore',
|
|||
'severe': 2,
|
||||
'critical': 3}
|
||||
|
||||
RETRY_ATTEMPTS = 90
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
|
@ -104,6 +102,51 @@ def __virtual__():
|
|||
return __virtualname__
|
||||
|
||||
|
||||
def _status_wait(service_name, end_time, service_states):
|
||||
'''
|
||||
Helper function that will wait for the status of the service to match the
|
||||
provided status before an end time expires. Used for service stop and start
|
||||
|
||||
.. versionadded:: 2017.7.9, 2018.3.4
|
||||
|
||||
Args:
|
||||
service_name (str):
|
||||
The name of the service
|
||||
|
||||
end_time (float):
|
||||
A future time. e.g. time.time() + 10
|
||||
|
||||
service_states (list):
|
||||
Services statuses to wait for as returned by info()
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing information about the service.
|
||||
|
||||
:codeauthor: Damon Atkins <https://github.com/damon-atkins>
|
||||
'''
|
||||
info_results = info(service_name)
|
||||
|
||||
while info_results['Status'] in service_states and time.time() < end_time:
|
||||
# From Microsoft: Do not wait longer than the wait hint. A good interval
|
||||
# is one-tenth of the wait hint but not less than 1 second and not more
|
||||
# than 10 seconds.
|
||||
# https://docs.microsoft.com/en-us/windows/desktop/services/starting-a-service
|
||||
# https://docs.microsoft.com/en-us/windows/desktop/services/stopping-a-service
|
||||
# Wait hint is in ms
|
||||
wait_time = info_results['Status_WaitHint']
|
||||
# Convert to seconds or 0
|
||||
wait_time = wait_time / 1000 if wait_time else 0
|
||||
if wait_time < 1:
|
||||
wait_time = 1
|
||||
elif wait_time > 10:
|
||||
wait_time = 10
|
||||
|
||||
time.sleep(wait_time)
|
||||
info_results = info(service_name)
|
||||
|
||||
return info_results
|
||||
|
||||
|
||||
def get_enabled():
|
||||
'''
|
||||
Return a list of enabled services. Enabled is defined as a service that is
|
||||
|
@ -378,7 +421,7 @@ def info(name):
|
|||
return ret
|
||||
|
||||
|
||||
def start(name):
|
||||
def start(name, timeout=90):
|
||||
'''
|
||||
Start the specified service.
|
||||
|
||||
|
@ -389,8 +432,14 @@ def start(name):
|
|||
Args:
|
||||
name (str): The name of the service to start
|
||||
|
||||
timeout (int):
|
||||
The time in seconds to wait for the service to start before
|
||||
returning. Default is 90 seconds
|
||||
|
||||
.. versionadded:: 2017.7.9, 2018.3.4
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -411,24 +460,28 @@ def start(name):
|
|||
raise CommandExecutionError(
|
||||
'Failed To Start {0}: {1}'.format(name, exc[2]))
|
||||
|
||||
attempts = 0
|
||||
while info(name)['Status'] in ['Start Pending', 'Stopped'] \
|
||||
and attempts <= RETRY_ATTEMPTS:
|
||||
time.sleep(1)
|
||||
attempts += 1
|
||||
srv_status = _status_wait(service_name=name,
|
||||
end_time=time.time() + int(timeout),
|
||||
service_states=['Start Pending', 'Stopped'])
|
||||
|
||||
return status(name)
|
||||
return srv_status['Status'] == 'Running'
|
||||
|
||||
|
||||
def stop(name):
|
||||
def stop(name, timeout=90):
|
||||
'''
|
||||
Stop the specified service
|
||||
|
||||
Args:
|
||||
name (str): The name of the service to stop
|
||||
|
||||
timeout (int):
|
||||
The time in seconds to wait for the service to stop before
|
||||
returning. Default is 90 seconds
|
||||
|
||||
.. versionadded:: 2017.7.9, 2018.3.4
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -436,15 +489,6 @@ def stop(name):
|
|||
|
||||
salt '*' service.stop <service name>
|
||||
'''
|
||||
# net stop issues a stop command and waits briefly (~30s), but will give
|
||||
# up if the service takes too long to stop with a misleading
|
||||
# "service could not be stopped" message and RC 0.
|
||||
|
||||
cmd = ['net', 'stop', '/y', name]
|
||||
res = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
if 'service was stopped' in res:
|
||||
return True
|
||||
|
||||
try:
|
||||
win32serviceutil.StopService(name)
|
||||
except pywintypes.error as exc:
|
||||
|
@ -452,28 +496,37 @@ def stop(name):
|
|||
raise CommandExecutionError(
|
||||
'Failed To Stop {0}: {1}'.format(name, exc[2]))
|
||||
|
||||
attempts = 0
|
||||
while info(name)['Status'] in ['Running', 'Stop Pending'] \
|
||||
and attempts <= RETRY_ATTEMPTS:
|
||||
time.sleep(1)
|
||||
attempts += 1
|
||||
srv_status = _status_wait(service_name=name,
|
||||
end_time=time.time() + int(timeout),
|
||||
service_states=['Running', 'Stop Pending'])
|
||||
|
||||
return not status(name)
|
||||
return srv_status['Status'] == 'Stopped'
|
||||
|
||||
|
||||
def restart(name):
|
||||
def restart(name, timeout=90):
|
||||
'''
|
||||
Restart the named service. This issues a stop command followed by a start.
|
||||
|
||||
Args:
|
||||
name: The name of the service to restart.
|
||||
|
||||
.. note::
|
||||
If the name passed is ``salt-minion`` a scheduled task is created and
|
||||
executed to restart the salt-minion service.
|
||||
.. note::
|
||||
If the name passed is ``salt-minion`` a scheduled task is
|
||||
created and executed to restart the salt-minion service.
|
||||
|
||||
timeout (int):
|
||||
The time in seconds to wait for the service to stop and start before
|
||||
returning. Default is 90 seconds
|
||||
|
||||
.. note::
|
||||
The timeout is cumulative meaning it is applied to the stop and
|
||||
then to the start command. A timeout of 90 could take up to 180
|
||||
seconds if the service is long in stopping and starting
|
||||
|
||||
.. versionadded:: 2017.7.9, 2018.3.4
|
||||
|
||||
Returns:
|
||||
bool: ``True`` if successful, ``False`` otherwise
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -485,7 +538,8 @@ def restart(name):
|
|||
create_win_salt_restart_task()
|
||||
return execute_salt_restart_task()
|
||||
|
||||
return stop(name) and start(name)
|
||||
return stop(name=name, timeout=timeout) and \
|
||||
start(name=name, timeout=timeout)
|
||||
|
||||
|
||||
def create_win_salt_restart_task():
|
||||
|
@ -531,7 +585,7 @@ def execute_salt_restart_task():
|
|||
return __salt__['task.run'](name='restart-salt-minion')
|
||||
|
||||
|
||||
def status(name, sig=None):
|
||||
def status(name, *args, **kwargs):
|
||||
'''
|
||||
Return the status for a service.
|
||||
If the name contains globbing, a dict mapping service name to True/False
|
||||
|
@ -542,7 +596,6 @@ def status(name, sig=None):
|
|||
|
||||
Args:
|
||||
name (str): The name of the service to check
|
||||
sig (str): Not supported on Windows
|
||||
|
||||
Returns:
|
||||
bool: True if running, False otherwise
|
||||
|
@ -610,20 +663,26 @@ def modify(name,
|
|||
.. versionadded:: 2016.11.0
|
||||
|
||||
Args:
|
||||
name (str): The name of the service. Can be found using the
|
||||
name (str):
|
||||
The name of the service. Can be found using the
|
||||
``service.get_service_name`` function
|
||||
|
||||
bin_path (str): The path to the service executable. Backslashes must be
|
||||
escaped, eg: C:\\path\\to\\binary.exe
|
||||
bin_path (str):
|
||||
The path to the service executable. Backslashes must be escaped, eg:
|
||||
``C:\\path\\to\\binary.exe``
|
||||
|
||||
exe_args (str): Any arguments required by the service executable
|
||||
exe_args (str):
|
||||
Any arguments required by the service executable
|
||||
|
||||
display_name (str): The name to display in the service manager
|
||||
display_name (str):
|
||||
The name to display in the service manager
|
||||
|
||||
description (str): The description to display for the service
|
||||
description (str):
|
||||
The description to display for the service
|
||||
|
||||
service_type (str): Specifies the service type. Default is ``own``.
|
||||
Valid options are as follows:
|
||||
service_type (str):
|
||||
Specifies the service type. Default is ``own``. Valid options are as
|
||||
follows:
|
||||
|
||||
- kernel: Driver service
|
||||
- filesystem: File system driver service
|
||||
|
@ -632,8 +691,8 @@ def modify(name,
|
|||
- own (default): Service runs in its own process
|
||||
- share: Service shares a process with one or more other services
|
||||
|
||||
start_type (str): Specifies the service start type. Valid options are as
|
||||
follows:
|
||||
start_type (str):
|
||||
Specifies the service start type. Valid options are as follows:
|
||||
|
||||
- boot: Device driver that is loaded by the boot loader
|
||||
- system: Device driver that is started during kernel initialization
|
||||
|
@ -641,13 +700,14 @@ def modify(name,
|
|||
- manual: Service must be started manually
|
||||
- disabled: Service cannot be started
|
||||
|
||||
start_delayed (bool): Set the service to Auto(Delayed Start). Only valid
|
||||
if the start_type is set to ``Auto``. If service_type is not passed,
|
||||
but the service is already set to ``Auto``, then the flag will be
|
||||
set.
|
||||
start_delayed (bool):
|
||||
Set the service to Auto(Delayed Start). Only valid if the start_type
|
||||
is set to ``Auto``. If service_type is not passed, but the service
|
||||
is already set to ``Auto``, then the flag will be set.
|
||||
|
||||
error_control (str): The severity of the error, and action taken, if
|
||||
this service fails to start. Valid options are as follows:
|
||||
error_control (str):
|
||||
The severity of the error, and action taken, if this service fails
|
||||
to start. Valid options are as follows:
|
||||
|
||||
- normal: Error is logged and a message box is displayed
|
||||
- severe: Error is logged and computer attempts a restart with the
|
||||
|
@ -657,29 +717,33 @@ def modify(name,
|
|||
- ignore: Error is logged and startup continues, no notification is
|
||||
given to the user
|
||||
|
||||
load_order_group: The name of the load order group to which this service
|
||||
belongs
|
||||
load_order_group (str):
|
||||
The name of the load order group to which this service belongs
|
||||
|
||||
dependencies (list): A list of services or load ordering groups that
|
||||
must start before this service
|
||||
dependencies (list):
|
||||
A list of services or load ordering groups that must start before
|
||||
this service
|
||||
|
||||
account_name (str): The name of the account under which the service
|
||||
should run. For ``own`` type services this should be in the
|
||||
``domain\\username`` format. The following are examples of valid
|
||||
built-in service accounts:
|
||||
account_name (str):
|
||||
The name of the account under which the service should run. For
|
||||
``own`` type services this should be in the ``domain\\username``
|
||||
format. The following are examples of valid built-in service
|
||||
accounts:
|
||||
|
||||
- NT Authority\\LocalService
|
||||
- NT Authority\\NetworkService
|
||||
- NT Authority\\LocalSystem
|
||||
- .\LocalSystem
|
||||
|
||||
account_password (str): The password for the account name specified in
|
||||
``account_name``. For the above built-in accounts, this can be None.
|
||||
Otherwise a password must be specified.
|
||||
account_password (str):
|
||||
The password for the account name specified in ``account_name``. For
|
||||
the above built-in accounts, this can be None. Otherwise a password
|
||||
must be specified.
|
||||
|
||||
run_interactive (bool): If this setting is True, the service will be
|
||||
allowed to interact with the user. Not recommended for services that
|
||||
run with elevated privileges.
|
||||
run_interactive (bool):
|
||||
If this setting is True, the service will be allowed to interact
|
||||
with the user. Not recommended for services that run with elevated
|
||||
privileges.
|
||||
|
||||
Returns:
|
||||
dict: a dictionary of changes made
|
||||
|
@ -936,20 +1000,26 @@ def create(name,
|
|||
|
||||
Args:
|
||||
|
||||
name (str): Specifies the service name. This is not the display_name
|
||||
name (str):
|
||||
Specifies the service name. This is not the display_name
|
||||
|
||||
bin_path (str): Specifies the path to the service binary file.
|
||||
Backslashes must be escaped, eg: C:\\path\\to\\binary.exe
|
||||
bin_path (str):
|
||||
Specifies the path to the service binary file. Backslashes must be
|
||||
escaped, eg: ``C:\\path\\to\\binary.exe``
|
||||
|
||||
exe_args (str): Any additional arguments required by the service binary.
|
||||
exe_args (str):
|
||||
Any additional arguments required by the service binary.
|
||||
|
||||
display_name (str): the name to be displayed in the service manager. If
|
||||
not passed, the ``name`` will be used
|
||||
display_name (str):
|
||||
The name to be displayed in the service manager. If not passed, the
|
||||
``name`` will be used
|
||||
|
||||
description (str): A description of the service
|
||||
description (str):
|
||||
A description of the service
|
||||
|
||||
service_type (str): Specifies the service type. Default is ``own``.
|
||||
Valid options are as follows:
|
||||
service_type (str):
|
||||
Specifies the service type. Default is ``own``. Valid options are as
|
||||
follows:
|
||||
|
||||
- kernel: Driver service
|
||||
- filesystem: File system driver service
|
||||
|
@ -958,8 +1028,8 @@ def create(name,
|
|||
- own (default): Service runs in its own process
|
||||
- share: Service shares a process with one or more other services
|
||||
|
||||
start_type (str): Specifies the service start type. Valid options are as
|
||||
follows:
|
||||
start_type (str):
|
||||
Specifies the service start type. Valid options are as follows:
|
||||
|
||||
- boot: Device driver that is loaded by the boot loader
|
||||
- system: Device driver that is started during kernel initialization
|
||||
|
@ -967,13 +1037,15 @@ def create(name,
|
|||
- manual (default): Service must be started manually
|
||||
- disabled: Service cannot be started
|
||||
|
||||
start_delayed (bool): Set the service to Auto(Delayed Start). Only valid
|
||||
if the start_type is set to ``Auto``. If service_type is not passed,
|
||||
but the service is already set to ``Auto``, then the flag will be
|
||||
set. Default is ``False``
|
||||
start_delayed (bool):
|
||||
Set the service to Auto(Delayed Start). Only valid if the start_type
|
||||
is set to ``Auto``. If service_type is not passed, but the service
|
||||
is already set to ``Auto``, then the flag will be set. Default is
|
||||
``False``
|
||||
|
||||
error_control (str): The severity of the error, and action taken, if
|
||||
this service fails to start. Valid options are as follows:
|
||||
error_control (str):
|
||||
The severity of the error, and action taken, if this service fails
|
||||
to start. Valid options are as follows:
|
||||
|
||||
- normal (normal): Error is logged and a message box is displayed
|
||||
- severe: Error is logged and computer attempts a restart with the
|
||||
|
@ -983,29 +1055,33 @@ def create(name,
|
|||
- ignore: Error is logged and startup continues, no notification is
|
||||
given to the user
|
||||
|
||||
load_order_group: The name of the load order group to which this service
|
||||
belongs
|
||||
load_order_group (str):
|
||||
The name of the load order group to which this service belongs
|
||||
|
||||
dependencies (list): A list of services or load ordering groups that
|
||||
must start before this service
|
||||
dependencies (list):
|
||||
A list of services or load ordering groups that must start before
|
||||
this service
|
||||
|
||||
account_name (str): The name of the account under which the service
|
||||
should run. For ``own`` type services this should be in the
|
||||
``domain\\username`` format. The following are examples of valid
|
||||
built-in service accounts:
|
||||
account_name (str):
|
||||
The name of the account under which the service should run. For
|
||||
``own`` type services this should be in the ``domain\\username``
|
||||
format. The following are examples of valid built-in service
|
||||
accounts:
|
||||
|
||||
- NT Authority\\LocalService
|
||||
- NT Authority\\NetworkService
|
||||
- NT Authority\\LocalSystem
|
||||
- .\\LocalSystem
|
||||
|
||||
account_password (str): The password for the account name specified in
|
||||
``account_name``. For the above built-in accounts, this can be None.
|
||||
Otherwise a password must be specified.
|
||||
account_password (str):
|
||||
The password for the account name specified in ``account_name``. For
|
||||
the above built-in accounts, this can be None. Otherwise a password
|
||||
must be specified.
|
||||
|
||||
run_interactive (bool): If this setting is True, the service will be
|
||||
allowed to interact with the user. Not recommended for services that
|
||||
run with elevated privileges.
|
||||
run_interactive (bool):
|
||||
If this setting is True, the service will be allowed to interact
|
||||
with the user. Not recommended for services that run with elevated
|
||||
privileges.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing information about the new service
|
||||
|
@ -1096,15 +1172,23 @@ def create(name,
|
|||
return info(name)
|
||||
|
||||
|
||||
def delete(name):
|
||||
def delete(name, timeout=90):
|
||||
'''
|
||||
Delete the named service
|
||||
|
||||
Args:
|
||||
|
||||
name (str): The name of the service to delete
|
||||
|
||||
timeout (int):
|
||||
The time in seconds to wait for the service to be deleted before
|
||||
returning. This is necessary because a service must be stopped
|
||||
before it can be deleted. Default is 90 seconds
|
||||
|
||||
.. versionadded:: 2017.7.9, 2018.3.4
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
bool: ``True`` if successful, otherwise ``False``
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -1120,16 +1204,20 @@ def delete(name):
|
|||
handle_scm, name, win32service.SERVICE_ALL_ACCESS)
|
||||
except pywintypes.error as exc:
|
||||
raise CommandExecutionError(
|
||||
'Failed To Open {0}: {1}'.format(name, exc[2]))
|
||||
'Failed to open {0}. {1}'.format(name, exc.strerror))
|
||||
|
||||
win32service.DeleteService(handle_svc)
|
||||
try:
|
||||
win32service.DeleteService(handle_svc)
|
||||
except pywintypes.error as exc:
|
||||
raise CommandExecutionError(
|
||||
'Failed to delete {0}. {1}'.format(name, exc.strerror))
|
||||
finally:
|
||||
log.debug('Cleaning up')
|
||||
win32service.CloseServiceHandle(handle_scm)
|
||||
win32service.CloseServiceHandle(handle_svc)
|
||||
|
||||
win32service.CloseServiceHandle(handle_scm)
|
||||
win32service.CloseServiceHandle(handle_svc)
|
||||
|
||||
attempts = 0
|
||||
while name in get_all() and attempts <= RETRY_ATTEMPTS:
|
||||
end_time = time.time() + int(timeout)
|
||||
while name in get_all() and time.time() < end_time:
|
||||
time.sleep(1)
|
||||
attempts += 1
|
||||
|
||||
return name not in get_all()
|
||||
|
|
|
@ -111,12 +111,14 @@ class NestDisplay(object):
|
|||
)
|
||||
# Number includes all python numbers types
|
||||
# (float, int, long, complex, ...)
|
||||
# use repr() to get the full precision also for older python versions
|
||||
# as until about python32 it was limited to 12 digits only by default
|
||||
elif isinstance(ret, Number):
|
||||
out.append(
|
||||
self.ustring(
|
||||
indent,
|
||||
self.LIGHT_YELLOW,
|
||||
ret,
|
||||
repr(ret),
|
||||
prefix=prefix
|
||||
)
|
||||
)
|
||||
|
|
|
@ -2656,8 +2656,15 @@ def managed(name,
|
|||
ret['changes'] = {}
|
||||
log.debug(traceback.format_exc())
|
||||
salt.utils.files.remove(tmp_filename)
|
||||
if not keep_source and sfn:
|
||||
salt.utils.files.remove(sfn)
|
||||
if not keep_source:
|
||||
if not sfn \
|
||||
and source \
|
||||
and _urlparse(source).scheme == 'salt':
|
||||
# The file would not have been cached until manage_file was
|
||||
# run, so check again here for a cached copy.
|
||||
sfn = __salt__['cp.is_cached'](source, __env__)
|
||||
if sfn:
|
||||
salt.utils.files.remove(sfn)
|
||||
return _error(ret, 'Unable to check_cmd file: {0}'.format(exc))
|
||||
|
||||
# file being updated to verify using check_cmd
|
||||
|
@ -2729,8 +2736,15 @@ def managed(name,
|
|||
finally:
|
||||
if tmp_filename:
|
||||
salt.utils.files.remove(tmp_filename)
|
||||
if not keep_source and sfn:
|
||||
salt.utils.files.remove(sfn)
|
||||
if not keep_source:
|
||||
if not sfn \
|
||||
and source \
|
||||
and _urlparse(source).scheme == 'salt':
|
||||
# The file would not have been cached until manage_file was
|
||||
# run, so check again here for a cached copy.
|
||||
sfn = __salt__['cp.is_cached'](source, __env__)
|
||||
if sfn:
|
||||
salt.utils.files.remove(sfn)
|
||||
|
||||
|
||||
_RECURSE_TYPES = ['user', 'group', 'mode', 'ignore_files', 'ignore_dirs']
|
||||
|
|
|
@ -199,6 +199,21 @@ def mounted(name,
|
|||
|
||||
update_mount_cache = False
|
||||
|
||||
if not name:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Must provide name to mount.mounted'
|
||||
return ret
|
||||
|
||||
if not device:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Must provide device to mount.mounted'
|
||||
return ret
|
||||
|
||||
if not fstype:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Must provide fstype to mount.mounted'
|
||||
return ret
|
||||
|
||||
if device_name_regex is None:
|
||||
device_name_regex = []
|
||||
|
||||
|
@ -588,11 +603,11 @@ def mounted(name,
|
|||
if __opts__['test']:
|
||||
if __grains__['os'] in ['MacOS', 'Darwin']:
|
||||
out = __salt__['mount.set_automaster'](name,
|
||||
device,
|
||||
fstype,
|
||||
opts,
|
||||
config,
|
||||
test=True)
|
||||
device,
|
||||
fstype,
|
||||
opts,
|
||||
config,
|
||||
test=True)
|
||||
elif __grains__['os'] in ['AIX']:
|
||||
out = __salt__['mount.set_filesystems'](name,
|
||||
device,
|
||||
|
@ -646,10 +661,10 @@ def mounted(name,
|
|||
else:
|
||||
if __grains__['os'] in ['MacOS', 'Darwin']:
|
||||
out = __salt__['mount.set_automaster'](name,
|
||||
device,
|
||||
fstype,
|
||||
opts,
|
||||
config)
|
||||
device,
|
||||
fstype,
|
||||
opts,
|
||||
config)
|
||||
elif __grains__['os'] in ['AIX']:
|
||||
out = __salt__['mount.set_filesystems'](name,
|
||||
device,
|
||||
|
@ -830,6 +845,11 @@ def unmounted(name,
|
|||
|
||||
update_mount_cache = False
|
||||
|
||||
if not name:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Must provide name to mount.unmounted'
|
||||
return ret
|
||||
|
||||
# Get the active data
|
||||
active = __salt__['mount.active'](extended=True)
|
||||
if name not in active:
|
||||
|
|
|
@ -437,16 +437,15 @@ def running(name,
|
|||
ret['comment'] = 'Service {0} is set to start'.format(name)
|
||||
return ret
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
if enable is True:
|
||||
ret.update(_enable(name, False, result=False, **kwargs))
|
||||
|
||||
# Conditionally add systemd-specific args to call to service.start
|
||||
start_kwargs, warnings = \
|
||||
_get_systemd_only(__salt__['service.start'], locals())
|
||||
if warnings:
|
||||
ret.setdefault('warnings', []).extend(warnings)
|
||||
|
||||
if salt.utils.platform.is_windows() and kwargs.get('timeout', False):
|
||||
start_kwargs.update({'timeout': kwargs.get('timeout')})
|
||||
|
||||
try:
|
||||
func_ret = __salt__['service.start'](name, **start_kwargs)
|
||||
except CommandExecutionError as exc:
|
||||
|
@ -590,6 +589,9 @@ def dead(name,
|
|||
if warnings:
|
||||
ret.setdefault('warnings', []).extend(warnings)
|
||||
|
||||
if salt.utils.platform.is_windows() and kwargs.get('timeout', False):
|
||||
stop_kwargs.update({'timeout': kwargs.get('timeout')})
|
||||
|
||||
func_ret = __salt__['service.stop'](name, **stop_kwargs)
|
||||
if not func_ret:
|
||||
ret['result'] = False
|
||||
|
|
|
@ -5,16 +5,13 @@ Utilities to enable exception reraising across the master commands
|
|||
'''
|
||||
from __future__ import absolute_import, unicode_literals, print_function
|
||||
|
||||
# Import python libs
|
||||
try:
|
||||
import exceptions
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Import salt libs
|
||||
import salt.exceptions
|
||||
import salt.utils.event
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext.six.moves import builtins as exceptions
|
||||
|
||||
|
||||
def raise_error(name=None, args=None, message=''):
|
||||
'''
|
||||
|
|
|
@ -706,7 +706,7 @@ class CkMinions(object):
|
|||
'S': 'ipcidr',
|
||||
'E': 'pcre',
|
||||
'N': 'node',
|
||||
None: 'glob'}
|
||||
None: 'compound'}
|
||||
|
||||
target_info = parse_target(auth_entry)
|
||||
if not target_info:
|
||||
|
|
|
@ -1126,7 +1126,10 @@ class TestDaemon(object):
|
|||
for dirname in (TMP, RUNTIME_VARS.TMP_STATE_TREE,
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE, RUNTIME_VARS.TMP_PRODENV_STATE_TREE):
|
||||
if os.path.isdir(dirname):
|
||||
shutil.rmtree(six.text_type(dirname), onerror=remove_readonly)
|
||||
try:
|
||||
shutil.rmtree(six.text_type(dirname), onerror=remove_readonly)
|
||||
except Exception:
|
||||
log.exception('Failed to remove directory: %s', dirname)
|
||||
|
||||
def wait_for_jid(self, targets, jid, timeout=120):
|
||||
time.sleep(1) # Allow some time for minions to accept jobs
|
||||
|
|
|
@ -7,4 +7,4 @@ azure-test:
|
|||
ssh_username: ''
|
||||
ssh_password: ''
|
||||
media_link: ''
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
|
|
|
@ -2,4 +2,4 @@ digitalocean-test:
|
|||
provider: digitalocean-config
|
||||
image: 14.04.5 x64
|
||||
size: 2GB
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
|
|
|
@ -3,7 +3,7 @@ ec2-test:
|
|||
image: ami-98aa1cf0
|
||||
size: m1.large
|
||||
sh_username: ec2-user
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
ec2-win2012r2-test:
|
||||
provider: ec2-config
|
||||
size: m1.large
|
||||
|
|
|
@ -2,4 +2,4 @@ gogrid-test:
|
|||
provider: gogrid-config
|
||||
size: 512MB
|
||||
image: Ubuntu 14.04 LTS Server (64-bit) w/ None
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
|
|
|
@ -3,4 +3,4 @@ joyent-test:
|
|||
size: k4-highcpu-kvm-250M
|
||||
image: ubuntu-16.04
|
||||
location: us-east-1
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
|
|
|
@ -2,4 +2,4 @@ linode-test:
|
|||
provider: linode-config
|
||||
size: Linode 2GB
|
||||
image: Ubuntu 14.04 LTS
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
|
|
|
@ -2,4 +2,4 @@ rackspace-test:
|
|||
provider: openstack-config
|
||||
size: 2 GB Performance
|
||||
image: Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)
|
||||
script_args: '-P -Z'
|
||||
script_args: '-P'
|
||||
|
|
|
@ -363,7 +363,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
with salt.utils.files.fopen(grain_path, 'r') as fp_:
|
||||
file_contents = fp_.readlines()
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
if IS_WINDOWS:
|
||||
match = '^minion\r\n'
|
||||
else:
|
||||
match = '^minion\n'
|
||||
|
@ -592,8 +592,8 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
name = os.path.join(TMP, 'local_source_with_source_hash')
|
||||
local_path = os.path.join(BASE_FILES, 'grail', 'scene33')
|
||||
actual_hash = '567fd840bf1548edc35c48eb66cdd78bfdfcccff'
|
||||
if salt.utils.platform.is_windows():
|
||||
# CRLF vs LF causes a differnt hash on windows
|
||||
if IS_WINDOWS:
|
||||
# CRLF vs LF causes a different hash on windows
|
||||
actual_hash = 'f658a0ec121d9c17088795afcc6ff3c43cb9842a'
|
||||
# Reverse the actual hash
|
||||
bad_hash = actual_hash[::-1]
|
||||
|
@ -677,7 +677,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'-{0}_|-managed'.format(name)
|
||||
local_path = os.path.join(BASE_FILES, 'hello_world.txt')
|
||||
actual_hash = 'c98c24b677eff44860afea6f493bbaec5bb1c4cbb209c6fc2bbb47f66ff2ad31'
|
||||
if salt.utils.platform.is_windows():
|
||||
if IS_WINDOWS:
|
||||
# CRLF vs LF causes a differnt hash on windows
|
||||
actual_hash = '92b772380a3f8e27a93e57e6deeca6c01da07f5aadce78bb2fbb20de10a66925'
|
||||
uppercase_hash = actual_hash.upper()
|
||||
|
@ -743,6 +743,29 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
diff_lines = ret['changes']['diff'].split(os.linesep)
|
||||
assert '+räksmörgås' in diff_lines, diff_lines
|
||||
|
||||
@with_tempfile()
|
||||
def test_managed_keep_source_false_salt(self, name):
|
||||
'''
|
||||
This test ensures that we properly clean the cached file if keep_source
|
||||
is set to False, for source files using a salt:// URL
|
||||
'''
|
||||
source = 'salt://grail/scene33'
|
||||
saltenv = 'base'
|
||||
|
||||
# Run the state
|
||||
ret = self.run_state(
|
||||
'file.managed',
|
||||
name=name,
|
||||
source=source,
|
||||
saltenv=saltenv,
|
||||
keep_source=False)
|
||||
ret = ret[next(iter(ret))]
|
||||
assert ret['result'] is True
|
||||
|
||||
# Now make sure that the file is not cached
|
||||
result = self.run_function('cp.is_cached', [source, saltenv])
|
||||
assert result == '', 'File is still cached at {0}'.format(result)
|
||||
|
||||
def test_directory(self):
|
||||
'''
|
||||
file.directory
|
||||
|
@ -861,14 +884,10 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.assertFalse(os.path.exists(straydir))
|
||||
self.assertTrue(os.path.isdir(name))
|
||||
|
||||
@skipIf(salt.utils.platform.is_windows(), 'Skip on windows')
|
||||
@with_tempdir()
|
||||
def test_directory_clean_exclude(self, base_dir):
|
||||
'''
|
||||
file.directory with clean=True and exclude_pat set
|
||||
|
||||
Skipped on windows because clean and exclude_pat not supported by
|
||||
salt.sates.file._check_directory_win
|
||||
'''
|
||||
name = os.path.join(base_dir, 'directory_clean_dir')
|
||||
if not os.path.isdir(name):
|
||||
|
@ -904,11 +923,14 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.assertFalse(os.path.exists(strayfile2))
|
||||
self.assertTrue(os.path.exists(keepfile))
|
||||
|
||||
@skipIf(salt.utils.is_windows(), 'Skip on windows')
|
||||
@skipIf(IS_WINDOWS, 'Skip on windows')
|
||||
@with_tempdir()
|
||||
def test_test_directory_clean_exclude(self, base_dir):
|
||||
'''
|
||||
file.directory with test=True, clean=True and exclude_pat set
|
||||
|
||||
Skipped on windows because clean and exclude_pat not supported by
|
||||
salt.sates.file._check_directory_win
|
||||
'''
|
||||
name = os.path.join(base_dir, 'directory_clean_dir')
|
||||
os.mkdir(name)
|
||||
|
@ -1231,7 +1253,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
self.assertTrue(os.path.isfile(os.path.join(name, '32', 'scene')))
|
||||
self.assertTrue(os.path.isfile(os.path.join(name, 'scene34')))
|
||||
|
||||
@skipIf(salt.utils.platform.is_windows(), 'Skip on windows')
|
||||
@skipIf(IS_WINDOWS, 'Skip on windows')
|
||||
@with_tempdir()
|
||||
def test_recurse_issue_34945(self, base_dir):
|
||||
'''
|
||||
|
@ -1273,7 +1295,7 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
name=name,
|
||||
source='salt://соль')
|
||||
self.assertSaltTrueReturn(ret)
|
||||
if six.PY2 and salt.utils.platform.is_windows():
|
||||
if six.PY2 and IS_WINDOWS:
|
||||
# Providing unicode to os.listdir so that we avoid having listdir
|
||||
# try to decode the filenames using the systemencoding on windows
|
||||
# python 2.
|
||||
|
@ -2496,18 +2518,18 @@ class FileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
class BlockreplaceTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
marker_start = '# start'
|
||||
marker_end = '# end'
|
||||
content = os.linesep.join([
|
||||
content = six.text_type(os.linesep.join([
|
||||
'Line 1 of block',
|
||||
'Line 2 of block',
|
||||
''
|
||||
])
|
||||
without_block = os.linesep.join([
|
||||
]))
|
||||
without_block = six.text_type(os.linesep.join([
|
||||
'Hello world!',
|
||||
'',
|
||||
'# comment here',
|
||||
''
|
||||
])
|
||||
with_non_matching_block = os.linesep.join([
|
||||
]))
|
||||
with_non_matching_block = six.text_type(os.linesep.join([
|
||||
'Hello world!',
|
||||
'',
|
||||
'# start',
|
||||
|
@ -2515,16 +2537,16 @@ class BlockreplaceTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'# end',
|
||||
'# comment here',
|
||||
''
|
||||
])
|
||||
with_non_matching_block_and_marker_end_not_after_newline = os.linesep.join([
|
||||
]))
|
||||
with_non_matching_block_and_marker_end_not_after_newline = six.text_type(os.linesep.join([
|
||||
'Hello world!',
|
||||
'',
|
||||
'# start',
|
||||
'No match here# end',
|
||||
'# comment here',
|
||||
''
|
||||
])
|
||||
with_matching_block = os.linesep.join([
|
||||
]))
|
||||
with_matching_block = six.text_type(os.linesep.join([
|
||||
'Hello world!',
|
||||
'',
|
||||
'# start',
|
||||
|
@ -2533,8 +2555,8 @@ class BlockreplaceTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'# end',
|
||||
'# comment here',
|
||||
''
|
||||
])
|
||||
with_matching_block_and_extra_newline = os.linesep.join([
|
||||
]))
|
||||
with_matching_block_and_extra_newline = six.text_type(os.linesep.join([
|
||||
'Hello world!',
|
||||
'',
|
||||
'# start',
|
||||
|
@ -2544,8 +2566,8 @@ class BlockreplaceTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'# end',
|
||||
'# comment here',
|
||||
''
|
||||
])
|
||||
with_matching_block_and_marker_end_not_after_newline = os.linesep.join([
|
||||
]))
|
||||
with_matching_block_and_marker_end_not_after_newline = six.text_type(os.linesep.join([
|
||||
'Hello world!',
|
||||
'',
|
||||
'# start',
|
||||
|
@ -2553,7 +2575,7 @@ class BlockreplaceTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
'Line 2 of block# end',
|
||||
'# comment here',
|
||||
''
|
||||
])
|
||||
]))
|
||||
content_explicit_posix_newlines = ('Line 1 of block\n'
|
||||
'Line 2 of block\n')
|
||||
content_explicit_windows_newlines = ('Line 1 of block\r\n'
|
||||
|
@ -3711,8 +3733,8 @@ class RemoteFileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
cls.webserver = Webserver()
|
||||
cls.webserver.start()
|
||||
cls.source = cls.webserver.url('grail/scene33')
|
||||
if salt.utils.platform.is_windows():
|
||||
# CRLF vs LF causes a differnt hash on windows
|
||||
if IS_WINDOWS:
|
||||
# CRLF vs LF causes a different hash on windows
|
||||
cls.source_hash = '21438b3d5fd2c0028bcab92f7824dc69'
|
||||
else:
|
||||
cls.source_hash = 'd2feb3beb323c79fc7a0f44f1408b4a3'
|
||||
|
@ -3732,6 +3754,11 @@ class RemoteFileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
if exc.errno != errno.ENOENT:
|
||||
raise exc
|
||||
|
||||
def run_state(self, *args, **kwargs):
|
||||
ret = super(RemoteFileTest, self).run_state(*args, **kwargs)
|
||||
log.debug('ret = %s', ret)
|
||||
return ret
|
||||
|
||||
def test_file_managed_http_source_no_hash(self):
|
||||
'''
|
||||
Test a remote file with no hash
|
||||
|
@ -3740,7 +3767,6 @@ class RemoteFileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
name=self.name,
|
||||
source=self.source,
|
||||
skip_verify=False)
|
||||
log.debug('ret = %s', ret)
|
||||
# This should fail because no hash was provided
|
||||
self.assertSaltFalseReturn(ret)
|
||||
|
||||
|
@ -3753,7 +3779,6 @@ class RemoteFileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
source=self.source,
|
||||
source_hash=self.source_hash,
|
||||
skip_verify=False)
|
||||
log.debug('ret = %s', ret)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
def test_file_managed_http_source_skip_verify(self):
|
||||
|
@ -3764,9 +3789,27 @@ class RemoteFileTest(ModuleCase, SaltReturnAssertsMixin):
|
|||
name=self.name,
|
||||
source=self.source,
|
||||
skip_verify=True)
|
||||
log.debug('ret = %s', ret)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
def test_file_managed_keep_source_false_http(self):
|
||||
'''
|
||||
This test ensures that we properly clean the cached file if keep_source
|
||||
is set to False, for source files using an http:// URL
|
||||
'''
|
||||
# Run the state
|
||||
ret = self.run_state('file.managed',
|
||||
name=self.name,
|
||||
source=self.source,
|
||||
source_hash=self.source_hash,
|
||||
keep_source=False)
|
||||
ret = ret[next(iter(ret))]
|
||||
assert ret['result'] is True
|
||||
|
||||
# Now make sure that the file is not cached
|
||||
result = self.run_function('cp.is_cached', [self.source])
|
||||
assert result == '', 'File is still cached at {0}'.format(result)
|
||||
|
||||
|
||||
WIN_TEST_FILE = 'c:/testfile'
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class CkMinionsTestCase(TestCase):
|
|||
TestCase for salt.utils.minions.CkMinions class
|
||||
'''
|
||||
def setUp(self):
|
||||
self.ckminions = salt.utils.minions.CkMinions({})
|
||||
self.ckminions = salt.utils.minions.CkMinions({'minion_data_cache': True})
|
||||
|
||||
def test_spec_check(self):
|
||||
# Test spec-only rule
|
||||
|
|
Loading…
Add table
Reference in a new issue