Merge pull request #51580 from garethgreenaway/merge-2018.3.4

[2018.3] Merge forward from 2018.3.4 to 2018.3
This commit is contained in:
Gareth J. Greenaway 2019-02-11 14:35:33 -08:00 committed by GitHub
commit 41e25a6627
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 6193 additions and 142 deletions

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-API" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-API" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-api \- salt-api Command
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-CALL" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-CALL" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-call \- salt-call Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-CLOUD" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-CLOUD" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-cloud \- Salt Cloud Command
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-CP" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-CP" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-cp \- salt-cp Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-KEY" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-KEY" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-key \- salt-key Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-MASTER" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-MASTER" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-master \- salt-master Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-MINION" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-MINION" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-minion \- salt-minion Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-PROXY" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-PROXY" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-proxy \- salt-proxy Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-RUN" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-RUN" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-run \- salt-run Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-SSH" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-SSH" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-ssh \- salt-ssh Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-SYNDIC" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-SYNDIC" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-syndic \- salt-syndic Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT-UNITY" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT-UNITY" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt-unity \- salt-unity Command
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt \- salt
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SALT" "7" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SALT" "7" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
salt \- Salt Documentation
.

View file

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SPM" "1" "Sep 21, 2018" "2018.3.3" "Salt"
.TH "SPM" "1" "Sep 21, 2018" "2018.3.4" "Salt"
.SH NAME
spm \- Salt Package Manager Command
.

File diff suppressed because it is too large Load diff

View file

@ -177,7 +177,7 @@ $MAKE install
############################################################################
echo -n -e "\033]0;Build_Env: libsodium: download\007"
PKGURL="https://download.libsodium.org/libsodium/releases/libsodium-1.0.15.tar.gz"
PKGURL="https://download.libsodium.org/libsodium/releases/old/libsodium-1.0.15.tar.gz"
PKGDIR="libsodium-1.0.15"
download $PKGURL

View file

@ -158,13 +158,20 @@ echo -n -e "\033]0;Build_Pkg: Add Version to .xml\007"
if [ "$PYVER" == "2" ]; then
TITLE="Salt $VERSION"
DESC="Salt $VERSION with Python 2"
SEDSTR="s/@PY2@/_py2/g"
else
TITLE="Salt $VERSION (Python 3)"
DESC="Salt $VERSION with Python 3"
SEDSTR="s/@PY2@//g"
fi
cd $PKGRESOURCES
cp distribution.xml.dist distribution.xml
# Select the appropriate welcome text
# This is only necessary until Sodium, then this can be removed
sed -E -i '' "$SEDSTR" distribution.xml
SEDSTR="s/@TITLE@/$TITLE/g"
sed -E -i '' "$SEDSTR" distribution.xml

View file

@ -16,7 +16,7 @@
mime-type="image/png"
scaling="proportional" />
<!-- Define documents displayed at various steps -->
<welcome file="welcome.rtf"
<welcome file="welcome@PY2@.rtf"
mime-type="text/rtf" />
<license file="license.rtf"
mime-type="text/rtf" />

View file

@ -0,0 +1,32 @@
{\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\froman\fcharset0 Times-Roman;\f2\fnil\fcharset0 PTMono-Regular;
}
{\colortbl;\red255\green255\blue255;\red0\green0\blue233;}
\vieww28300\viewh14680\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 WARNING: Python 2 Support will be discontinued in Sodium. Salt will only ship Python 3 installers starting with the Sodium release.\
\
\pard\pardeftab720\sl280\sa240\partightenfactor0
{\field{\*\fldinst{HYPERLINK "http://saltstack.com/"}}{\fldrslt
\f1 \cf2 \expnd0\expndtw0\kerning0
\ul \ulc2 SaltStack}}
\f1 \expnd0\expndtw0\kerning0
is extremely fast and scalable systems and configuration management software for predictive orchestration, cloud and data center automation, server provisioning, application deployment and more. \
Documentation for Salt is available at {\field{\*\fldinst{HYPERLINK "http://docs.saltstack.com/"}}{\fldrslt \cf2 \ul \ulc2 http://docs.saltstack.com}} \
This package will install Salt on your Mac. Salt installs into
\f2\fs22 /opt/salt
\f1\fs24 .\
Sample configuration files (
\f2\fs22 master.dist
\f1\fs24 and
\f2\fs22 minion.dist
\f1\fs24 ) will be installed to
\f2\fs22 /etc/salt
\f1\fs24 . Create copies of them without the '
\f2\fs22 .dist
\f1\fs24 ' in the filename and edit as you see fit.\
This Salt package uses a custom-built Python. To install additional Python modules for Salt, use the associated 'pip' binary. For example, if you need LDAP support in Salt you will need the 'python-ldap' module. Install it with
\f2\fs22 /opt/salt/bin/pip install python-ldap
\f1\fs24 \
Note that some Python modules need a compiler available. Installing Apple's Xcode Command Line Tools should provide the necessary utilities. Alternatively, {\field{\*\fldinst{HYPERLINK "http://macports.org/"}}{\fldrslt \cf2 \ul \ulc2 MacPorts}}, {\field{\*\fldinst{HYPERLINK "http://finkproject.org/"}}{\fldrslt \cf2 \ul \ulc2 Fink}}, or {\field{\*\fldinst{HYPERLINK "http://brew.sh/"}}{\fldrslt \cf2 \ul \ulc2 Homebrew}} may provide what you need.}

View file

@ -70,6 +70,22 @@ ${StrStrAdv}
!define MUI_ICON "salt.ico"
!define MUI_UNICON "salt.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP "panel.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "panel.bmp"
# This entire if block can be removed for the Sodium release... including the !define MUI_WELCOMEPAGE_TEXT
# NSIS will just use the default like it does for Python 3, which should be the same test
!if "${PYTHON_VERSION}" == "2"
!define MUI_WELCOMEPAGE_TEXT "\
WARNING: Python 2 Support will be discontinued in Sodium. Salt will only ship Python 3 \
installers starting with the Sodium release.$\r$\n\
$\r$\n\
Setup will guide you through the installation of ${PRODUCT_NAME} ${PRODUCT_VERSION}.$\r$\n\
$\r$\n\
It is recommended that you close all other applications before starting Setup. This will make it possible to \
update relevant system files without having to reboot your computer.$\r$\n\
$\r$\n\
Click Next to continue."
!endif
# Welcome page
!insertmacro MUI_PAGE_WELCOME

View file

@ -1938,15 +1938,10 @@ PROVIDER_CONFIG_DEFAULTS = {
# <---- Salt Cloud Configuration Defaults ------------------------------------
def _validate_file_roots(file_roots):
def _normalize_roots(file_roots):
'''
If the file_roots option has a key that is None then we will error out,
just replace it with an empty list
Normalize file or pillar roots.
'''
if not isinstance(file_roots, dict):
log.warning('The file_roots parameter is not properly formatted,'
' using defaults')
return {'base': _expand_glob_path([salt.syspaths.BASE_FILE_ROOTS_DIR])}
for saltenv, dirs in six.iteritems(file_roots):
normalized_saltenv = six.text_type(saltenv)
if normalized_saltenv != saltenv:
@ -1958,6 +1953,30 @@ def _validate_file_roots(file_roots):
return file_roots
def _validate_pillar_roots(pillar_roots):
'''
If the pillar_roots option has a key that is None then we will error out,
just replace it with an empty list
'''
if not isinstance(pillar_roots, dict):
log.warning('The pillar_roots parameter is not properly formatted,'
' using defaults')
return {'base': _expand_glob_path([salt.syspaths.BASE_PILLAR_ROOTS_DIR])}
return _normalize_roots(pillar_roots)
def _validate_file_roots(file_roots):
'''
If the file_roots option has a key that is None then we will error out,
just replace it with an empty list
'''
if not isinstance(file_roots, dict):
log.warning('The file_roots parameter is not properly formatted,'
' using defaults')
return {'base': _expand_glob_path([salt.syspaths.BASE_FILE_ROOTS_DIR])}
return _normalize_roots(file_roots)
def _expand_glob_path(file_roots):
'''
Applies shell globbing to a set of directories and returns
@ -3767,7 +3786,7 @@ def apply_minion_config(overrides=None,
# nothing else!
opts['open_mode'] = opts['open_mode'] is True
opts['file_roots'] = _validate_file_roots(opts['file_roots'])
opts['pillar_roots'] = _validate_file_roots(opts['pillar_roots'])
opts['pillar_roots'] = _validate_pillar_roots(opts['pillar_roots'])
# Make sure ext_mods gets set if it is an untrue value
# (here to catch older bad configs)
opts['extension_modules'] = (

View file

@ -1266,6 +1266,7 @@ def user_exists(user,
'''
run_verify = False
server_version = version(**connection_args)
compare_version = '10.2.0' if 'MariaDB' in server_version else '8.0.11'
dbc = _connect(**connection_args)
# Did we fail to connect with the user we are checking
# Its password might have previously change with the same command/state
@ -1297,7 +1298,7 @@ def user_exists(user,
else:
qry += ' AND ' + password_column + ' = \'\''
elif password:
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
run_verify = True
else:
_password = password
@ -1404,6 +1405,7 @@ def user_create(user,
salt '*' mysql.user_create 'username' 'hostname' allow_passwordless=True
'''
server_version = version(**connection_args)
compare_version = '10.2.0' if 'MariaDB' in server_version else '8.0.11'
if user_exists(user, host, **connection_args):
log.info('User \'%s\'@\'%s\' already exists', user, host)
return False
@ -1424,7 +1426,7 @@ def user_create(user,
qry += ' IDENTIFIED BY %(password)s'
args['password'] = six.text_type(password)
elif password_hash is not None:
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
qry += ' IDENTIFIED BY %(password)s'
else:
qry += ' IDENTIFIED BY PASSWORD %(password)s'
@ -1508,9 +1510,10 @@ def user_chpass(user,
salt '*' mysql.user_chpass frank localhost allow_passwordless=True
'''
server_version = version(**connection_args)
compare_version = '10.2.0' if 'MariaDB' in server_version else '8.0.11'
args = {}
if password is not None:
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
password_sql = '%(password)s'
else:
password_sql = 'PASSWORD(%(password)s)'
@ -1533,28 +1536,23 @@ def user_chpass(user,
password_column = __password_column(**connection_args)
cur = dbc.cursor()
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
qry = ("ALTER USER '" + user + "'@'" + host + "'"
" IDENTIFIED BY '" + password + "';")
args = {}
args['user'] = user
args['host'] = host
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
qry = "ALTER USER %(user)s@%(host)s IDENTIFIED BY %(password)s;"
else:
qry = ('UPDATE mysql.user SET ' + password_column + '='
+ password_sql +
qry = ('UPDATE mysql.user SET ' + password_column + '=' + password_sql +
' WHERE User=%(user)s AND Host = %(host)s;')
args['user'] = user
args['host'] = host
if salt.utils.data.is_true(allow_passwordless) and \
salt.utils.data.is_true(unix_socket):
if host == 'localhost':
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
qry = ("ALTER USER '" + user + "'@'" + host + "'"
" IDENTIFIED BY '" + password + "';")
args = {}
args['unix_socket'] = 'auth_socket'
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
qry = "ALTER USER %(user)s@%(host)s IDENTIFIED WITH %(unix_socket)s AS %(user)s;"
else:
qry = ('UPDATE mysql.user SET ' + password_column + '='
+ password_sql + ', plugin=%(unix_socket)s' +
' WHERE User=%(user)s AND Host = %(host)s;')
args['unix_socket'] = 'unix_socket'
else:
log.error('Auth via unix_socket can be set only for host=localhost')
try:
@ -1565,7 +1563,7 @@ def user_chpass(user,
log.error(err)
return False
if salt.utils.versions.version_cmp(server_version, '8.0.11') >= 0:
if salt.utils.versions.version_cmp(server_version, compare_version) >= 0:
_execute(cur, 'FLUSH PRIVILEGES;')
log.info(
'Password for user \'%s\'@\'%s\' has been %s',
@ -1869,7 +1867,8 @@ def grant_exists(grant,
server_version = version(**connection_args)
if 'ALL' in grant:
if salt.utils.versions.version_cmp(server_version, '8.0') >= 0:
if salt.utils.versions.version_cmp(server_version, '8.0') >= 0 and \
'MariaDB' not in server_version:
grant = ','.join([i for i in __all_privileges__])
else:
grant = 'ALL PRIVILEGES'

View file

@ -1620,7 +1620,7 @@ def set_authentication_profile(profile=None, deploy=False):
'''
if not profile:
CommandExecutionError("Profile name option must not be none.")
raise CommandExecutionError("Profile name option must not be none.")
ret = {}
@ -1657,7 +1657,7 @@ def set_hostname(hostname=None, deploy=False):
'''
if not hostname:
CommandExecutionError("Hostname option must not be none.")
raise CommandExecutionError("Hostname option must not be none.")
ret = {}
@ -1697,7 +1697,7 @@ def set_management_icmp(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -1737,7 +1737,7 @@ def set_management_http(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -1777,7 +1777,7 @@ def set_management_https(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -1817,7 +1817,7 @@ def set_management_ocsp(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -1857,7 +1857,7 @@ def set_management_snmp(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -1897,7 +1897,7 @@ def set_management_ssh(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -1937,7 +1937,7 @@ def set_management_telnet(enabled=True, deploy=False):
elif enabled is False:
value = "yes"
else:
CommandExecutionError("Invalid option provided for service enabled option.")
raise CommandExecutionError("Invalid option provided for service enabled option.")
ret = {}
@ -2130,7 +2130,7 @@ def set_permitted_ip(address=None, deploy=False):
'''
if not address:
CommandExecutionError("Address option must not be empty.")
raise CommandExecutionError("Address option must not be empty.")
ret = {}
@ -2166,7 +2166,7 @@ def set_timezone(tz=None, deploy=False):
'''
if not tz:
CommandExecutionError("Timezone name option must not be none.")
raise CommandExecutionError("Timezone name option must not be none.")
ret = {}

View file

@ -19,7 +19,6 @@ import re
import subprocess
# Import salt libs
from salt.ext import six
import salt.utils.decorators.path
import salt.utils.data
import salt.utils.files
@ -44,9 +43,8 @@ if six.PY3:
def __virtual__():
# TODO: This could work on windows with some love
if salt.utils.platform.is_windows():
return (False, 'The module cannot be loaded on windows.')
if not salt.utils.path.which('ssh'):
return False, 'The module requires the ssh binary.'
return True
@ -753,9 +751,10 @@ def set_auth_key(
if not os.path.isdir(os.path.dirname(fconfig)):
dpath = os.path.dirname(fconfig)
os.makedirs(dpath)
if os.geteuid() == 0:
os.chown(dpath, uinfo['uid'], uinfo['gid'])
os.chmod(dpath, 448)
if not salt.utils.platform.is_windows():
if os.geteuid() == 0:
os.chown(dpath, uinfo['uid'], uinfo['gid'])
os.chmod(dpath, 448)
# If SELINUX is available run a restorecon on the file
rcon = salt.utils.path.which('restorecon')
if rcon:
@ -784,9 +783,10 @@ def set_auth_key(
raise CommandExecutionError(msg.format(exc))
if new_file:
if os.geteuid() == 0:
os.chown(fconfig, uinfo['uid'], uinfo['gid'])
os.chmod(fconfig, 384)
if not salt.utils.platform.is_windows():
if os.geteuid() == 0:
os.chown(fconfig, uinfo['uid'], uinfo['gid'])
os.chmod(fconfig, 384)
# If SELINUX is available run a restorecon on the file
rcon = salt.utils.path.which('restorecon')
if rcon:
@ -1104,10 +1104,11 @@ def rm_known_host(user=None, hostname=None, config=None, port=None):
ssh_hostname = _hostname_and_port_to_ssh_hostname(hostname, port)
cmd = ['ssh-keygen', '-R', ssh_hostname, '-f', full]
cmd_result = __salt__['cmd.run'](cmd, python_shell=False)
# ssh-keygen creates a new file, thus a chown is required.
if os.geteuid() == 0 and user:
uinfo = __salt__['user.info'](user)
os.chown(full, uinfo['uid'], uinfo['gid'])
if not salt.utils.platform.is_windows():
# ssh-keygen creates a new file, thus a chown is required.
if os.geteuid() == 0 and user:
uinfo = __salt__['user.info'](user)
os.chown(full, uinfo['uid'], uinfo['gid'])
return {'status': 'removed', 'comment': cmd_result}
@ -1317,12 +1318,13 @@ def set_known_host(user=None,
"Couldn't append to known hosts file: '{0}'".format(exception)
)
if os.geteuid() == 0 and user:
os.chown(full, uinfo['uid'], uinfo['gid'])
if origmode:
os.chmod(full, origmode)
else:
os.chmod(full, 0o600)
if not salt.utils.platform.is_windows():
if os.geteuid() == 0 and user:
os.chown(full, uinfo['uid'], uinfo['gid'])
if origmode:
os.chmod(full, origmode)
else:
os.chmod(full, 0o600)
if key and hash_known_hosts:
cmd_result = __salt__['ssh.hash_known_hosts'](user=user, config=full)
@ -1446,10 +1448,11 @@ def hash_known_hosts(user=None, config=None):
cmd = ['ssh-keygen', '-H', '-f', full]
cmd_result = __salt__['cmd.run'](cmd, python_shell=False)
os.chmod(full, origmode)
# ssh-keygen creates a new file, thus a chown is required.
if os.geteuid() == 0 and user:
uinfo = __salt__['user.info'](user)
os.chown(full, uinfo['uid'], uinfo['gid'])
if not salt.utils.platform.is_windows():
# ssh-keygen creates a new file, thus a chown is required.
if os.geteuid() == 0 and user:
uinfo = __salt__['user.info'](user)
os.chown(full, uinfo['uid'], uinfo['gid'])
return {'status': 'updated', 'comment': cmd_result}

View file

@ -739,7 +739,7 @@ def set_lcm_config(config_mode=None,
cmd += ' RefreshFrequencyMins = {0};'.format(refresh_freq)
if reboot_if_needed is not None:
if not isinstance(reboot_if_needed, bool):
SaltInvocationError('reboot_if_needed must be a boolean value')
raise SaltInvocationError('reboot_if_needed must be a boolean value')
if reboot_if_needed:
reboot_if_needed = '$true'
else:

View file

@ -5083,8 +5083,8 @@ def _findOptionValueAdvAudit(option):
field_names = _get_audit_defaults('fieldnames')
# If the file doesn't exist anywhere, create it with default
# fieldnames
__salt__['file.touch'](f_audit)
__salt__['file.append'](f_audit, ','.join(field_names))
__salt__['file.mkdir'](os.path.dirname(f_audit))
__salt__['file.write'](f_audit, ','.join(field_names))
audit_settings = {}
with salt.utils.files.fopen(f_audit, mode='r') as csv_file:
@ -5187,6 +5187,7 @@ def _set_audit_file_data(option, value):
# Copy the temporary csv file over the existing audit.csv in both
# locations if a value was written
__salt__['file.copy'](f_temp.name, f_audit, remove_existing=True)
__salt__['file.mkdir'](os.path.dirname(f_audit_gpo))
__salt__['file.copy'](f_temp.name, f_audit_gpo, remove_existing=True)
finally:
f_temp.close()

View file

@ -205,17 +205,22 @@ def get_zone():
Returns:
str: Timezone in unix format
Raises:
CommandExecutionError: If timezone could not be gathered
CLI Example:
.. code-block:: bash
salt '*' timezone.get_zone
'''
win_zone = __utils__['reg.read_value'](
hive='HKLM',
key='SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation',
vname='TimeZoneKeyName')['vdata']
return mapper.get_unix(win_zone.lower(), 'Unknown')
cmd = ['tzutil', '/g']
res = __salt__['cmd.run_all'](cmd, python_shell=False)
if res['retcode'] or not res['stdout']:
raise CommandExecutionError('tzutil encountered an error getting '
'timezone',
info=res)
return mapper.get_unix(res['stdout'].lower(), 'Unknown')
def get_offset():

View file

@ -46,6 +46,7 @@ try:
except ImportError:
HAS_DNSPYTHON = False
HAS_DIG = salt.utils.path.which('dig') is not None
DIG_OPTIONS = '+search +fail +noall +answer +nocl +nottl'
HAS_DRILL = salt.utils.path.which('drill') is not None
HAS_HOST = salt.utils.path.which('host') is not None
HAS_NSLOOKUP = salt.utils.path.which('nslookup') is not None
@ -230,7 +231,7 @@ def _lookup_dig(name, rdtype, timeout=None, servers=None, secure=None):
:param servers: [] of servers to use
:return: [] of records or False if error
'''
cmd = 'dig +search +fail +noall +answer +noclass +nottl -t {0} '.format(rdtype)
cmd = 'dig {0} -t {1} '.format(DIG_OPTIONS, rdtype)
if servers:
cmd += ''.join(['@{0} '.format(srv) for srv in servers])
if timeout is not None:

View file

@ -11,8 +11,8 @@
from __future__ import absolute_import, unicode_literals, print_function
# Import salt libs
from salt.ext import six
import salt.utils.files
import salt.utils.stringutils
from salt.exceptions import SaltException
@ -85,14 +85,11 @@ class BufferedReader(object):
multiplier = 1
self.__buffered = self.__buffered[self.__chunk_size:]
if six.PY3:
# Data is a byte object in Python 3
# Decode it in order to append to self.__buffered str later
data = self.__file.read(self.__chunk_size * multiplier).decode(
__salt_system_encoding__
)
else:
data = self.__file.read(self.__chunk_size * multiplier)
data = self.__file.read(self.__chunk_size * multiplier)
# Data is a byte object in Python 3
# Decode it in order to append to self.__buffered str later
# Use the salt util in case it's already a string (Windows)
data = salt.utils.stringutils.to_str(data)
if not data:
self.__file.close()

View file

@ -3006,7 +3006,11 @@ class GitPillar(GitBase):
elif repo.env:
env = repo.env
else:
env = 'base' if repo.branch == repo.base else repo.get_checkout_target()
if repo.branch == repo.base:
env = 'base'
else:
tgt = repo.get_checkout_target()
env = 'base' if tgt == repo.base else tgt
if repo._mountpoint:
if self.link_mountpoint(repo):
self.pillar_dirs[repo.linkdir] = env

View file

@ -1,5 +0,0 @@
# -*- coding: utf-8 -*-
def test(grains):
return {'custom_grain_test': 'itworked' if 'os' in grains else 'itdidntwork'}

View file

@ -15,6 +15,7 @@ from tests.support.helpers import skip_if_binaries_missing
# Import salt libs
import salt.utils.files
import salt.utils.platform
# Import 3rd-party libs
from tornado.httpclient import HTTPClient
@ -70,7 +71,10 @@ class SSHModuleTest(ModuleCase):
shutil.copyfile(
os.path.join(FILES, 'ssh', 'authorized_keys'),
AUTHORIZED_KEYS)
ret = self.run_function('ssh.auth_keys', ['root', AUTHORIZED_KEYS])
user = 'root'
if salt.utils.platform.is_windows():
user = 'Administrator'
ret = self.run_function('ssh.auth_keys', [user, AUTHORIZED_KEYS])
self.assertEqual(len(list(ret.items())), 1) # exactly one key is found
key_data = list(ret.items())[0][1]
try:

View file

@ -22,8 +22,12 @@ class WinDNSTest(ModuleCase):
'''
Test add and removing a dns server
'''
# Get a list of interfaces on the system
interfaces = self.run_function('network.interfaces_names')
skipIf(interfaces.count == 0, 'This test requires a network interface')
interface = interfaces[0]
dns = '8.8.8.8'
interface = 'Ethernet'
# add dns server
self.assertTrue(self.run_function('win_dns_client.add_dns', [dns, interface], index=42))

View file

@ -1 +1,32 @@
# -*- coding: utf-8 -*-
# Import python libs
from __future__ import absolute_import, print_function, unicode_literals
# Import Salt Testing Libs
from tests.support.unit import TestCase, skipIf
import tests.support.mock as mock
import salt.config
import salt.syspaths
class ConfigTest(TestCase):
def test_validate_bad_pillar_roots(self):
expected = salt.config._expand_glob_path(
[salt.syspaths.BASE_PILLAR_ROOTS_DIR]
)
with mock.patch('salt.config._normalize_roots') as mk:
ret = salt.config._validate_pillar_roots(None)
assert not mk.called
assert ret == {'base': expected}
def test_validate_bad_file_roots(self):
expected = salt.config._expand_glob_path(
[salt.syspaths.BASE_FILE_ROOTS_DIR]
)
with mock.patch('salt.config._normalize_roots') as mk:
ret = salt.config._validate_file_roots(None)
assert not mk.called
assert ret == {'base': expected}

View file

@ -99,6 +99,21 @@ class MySQLTestCase(TestCase, LoaderModuleMockMixin):
password='BLUECOW'
)
with patch.object(mysql, 'version', return_value='10.1.38-MariaDB'):
self._test_call(mysql.user_exists,
{'sql': ('SELECT User,Host FROM mysql.user WHERE '
'User = %(user)s AND Host = %(host)s AND '
'Password = PASSWORD(%(password)s)'),
'sql_args': {'host': 'localhost',
'password': 'BLUECOW',
'user': 'mytestuser'
}
},
user='mytestuser',
host='localhost',
password='BLUECOW'
)
with patch.object(mysql, 'version', return_value='8.0.11'):
self._test_call(mysql.user_exists,
{'sql': ('SELECT User,Host FROM mysql.user WHERE '
@ -125,6 +140,19 @@ class MySQLTestCase(TestCase, LoaderModuleMockMixin):
password='BLUECOW'
)
with patch.object(mysql, 'version', return_value='10.2.21-MariaDB'):
self._test_call(mysql.user_exists,
{'sql': ('SELECT User,Host FROM mysql.user WHERE '
'User = %(user)s AND Host = %(host)s'),
'sql_args': {'host': 'localhost',
'user': 'mytestuser'
}
},
user='mytestuser',
host='localhost',
password='BLUECOW'
)
# test_user_create_when_user_exists(self):
# ensure we don't try to create a user when one already exists
# mock the version of MySQL
@ -187,7 +215,11 @@ class MySQLTestCase(TestCase, LoaderModuleMockMixin):
mysql.user_chpass('testuser', password='BLUECOW')
calls = (
call().cursor().execute(
"ALTER USER 'testuser'@'localhost' IDENTIFIED BY 'BLUECOW';"
"ALTER USER %(user)s@%(host)s IDENTIFIED BY %(password)s;",
{'password': 'BLUECOW',
'user': 'testuser',
'host': 'localhost',
}
),
call().cursor().execute('FLUSH PRIVILEGES;'),
)

View file

@ -3,18 +3,15 @@
:codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
'''
# Import Python Libs
from __future__ import absolute_import, unicode_literals, print_function
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase, skipIf
from tests.support.mock import (
MagicMock,
patch
)
from __future__ import absolute_import, print_function, unicode_literals
# Import Salt Libs
import salt.modules.win_timezone as win_timezone
from salt.exceptions import CommandExecutionError
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, patch
from tests.support.unit import TestCase, skipIf
@skipIf(not win_timezone.HAS_PYTZ, 'This test requires pytz')
@ -25,20 +22,36 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {win_timezone: {}}
# 'get_zone' function tests: 1
# 'get_zone' function tests: 3
def test_get_zone(self):
'''
Test if it get current timezone (i.e. Asia/Calcutta)
'''
mock_read = MagicMock(side_effect=[{'vdata': 'India Standard Time'},
{'vdata': 'Indian Standard Time'}])
mock_read_ok = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read_ok}):
self.assertEqual(win_timezone.get_zone(), 'Asia/Calcutta')
mock_read_error = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': 'Indian Standard Time'})
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read_error}):
self.assertEqual(win_timezone.get_zone(), 'Unknown')
mock_read_fatal = MagicMock(return_value={'pid': 78,
'retcode': 1,
'stderr': '',
'stdout': ''})
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read_fatal}):
self.assertRaises(CommandExecutionError, win_timezone.get_zone)
# 'get_offset' function tests: 1
def test_get_offset(self):
@ -49,10 +62,12 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
# New Delhi\nIndia Standard Time')
# mock_cmd = MagicMock(side_effect=['India Standard Time', time])
# with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
mock_read = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': 'India Standard Time'})
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
self.assertEqual(win_timezone.get_offset(), '+0530')
# 'get_zonecode' function tests: 1
@ -61,9 +76,12 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it get current timezone (i.e. PST, MDT, etc)
'''
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
mock_read = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
self.assertEqual(win_timezone.get_zonecode(), 'IST')
# 'set_zone' function tests: 1
@ -72,14 +90,17 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it unlinks, then symlinks /etc/localtime to the set timezone.
'''
mock_cmd = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': ''})
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
mock_write = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': ''})
mock_read = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': 'India Standard Time'})
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_cmd}), \
patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_write}), \
patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
self.assertTrue(win_timezone.set_zone('Asia/Calcutta'))
@ -91,9 +112,12 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
the one set in /etc/localtime. Returns True if they match,
and False if not. Mostly useful for running state checks.
'''
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
mock_read = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_read}):
self.assertTrue(win_timezone.zone_compare('Asia/Calcutta'))
# 'get_hwclock' function tests: 1

View file

@ -775,10 +775,15 @@ class TestFileState(TestCase, LoaderModuleMockMixin):
with patch.object(os.path, 'exists', mock_t):
with patch.dict(filestate.__opts__, {'test': True}):
ret.update({'comment': comt})
self.assertDictEqual(filestate.managed
(name, user=user,
group=group,
mode=400), ret)
if salt.utils.is_windows():
self.assertDictEqual(filestate.managed
(name, user=user,
group=group), ret)
else:
self.assertDictEqual(filestate.managed
(name, user=user,
group=group,
mode=400), ret)
# 'directory' function tests: 1

View file

@ -15,6 +15,7 @@ import salt.utils.dns
from salt.utils.dns import _to_port, _tree, _weighted_order, _data2rec, _data2rec_group
from salt.utils.dns import _lookup_gai, _lookup_dig, _lookup_drill, _lookup_host, _lookup_nslookup
from salt.utils.dns import lookup
import salt.modules.cmdmod
# Testing
from tests.support.unit import skipIf, TestCase
@ -318,6 +319,12 @@ class DNSlookupsCase(TestCase):
lookup(rec, rec_t, method='nslookup', servers='8.8.8.8'), test_res,
)
@skipIf(not salt.utils.dns.HAS_DIG, 'dig is not available')
def test_dig_options(self):
cmd = 'dig {0} -v'.format(salt.utils.dns.DIG_OPTIONS)
cmd = salt.modules.cmdmod.retcode(cmd, python_shell=False, output_loglevel='quiet')
self.assertEqual(cmd, 0)
def test_dig(self):
wrong_type = {'retcode': 0, 'stderr': ';; Warning, ignoring invalid type ABC'}