mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge remote-tracking branch 'upstream/2015.5' into merge-forward-2015.8
Conflicts: salt/minion.py salt/modules/gpg.py salt/modules/keystone.py salt/modules/pw_user.py salt/states/reg.py setup.py
This commit is contained in:
commit
d3d0e004d9
37 changed files with 2967 additions and 476 deletions
|
@ -215,6 +215,48 @@ If you would like to log to the console instead of to the log file, remove the
|
||||||
</topics/installation/osx>` instructions.
|
</topics/installation/osx>` instructions.
|
||||||
|
|
||||||
|
|
||||||
|
Changing Default Paths
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Instead of updating your configuration files to point to the new root directory
|
||||||
|
and having to pass the new configuration directory path to all of Salt's CLI
|
||||||
|
tools, you can explicitly tweak the default system paths that Salt expects:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
GENERATE_SALT_SYSPATHS=1 pip --global-option='--salt-root-dir=/path/to/your/virtualenv/' \
|
||||||
|
install -e ./salt # the path to the salt git clone from above
|
||||||
|
|
||||||
|
|
||||||
|
You can now call all of Salt's CLI tools without explicitly passing the configuration directory.
|
||||||
|
|
||||||
|
Additional Options
|
||||||
|
..................
|
||||||
|
|
||||||
|
In case you want to distribute your virtualenv, you probably don't want to
|
||||||
|
include Salt's clone ``.git/`` directory, and, without it, Salt won't report
|
||||||
|
the accurate version. You can tell ``setup.py`` to generate the hardcoded
|
||||||
|
version information which is distributable:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
GENERATE_SALT_SYSPATHS=1 WRITE_SALT_VERSION=1 pip --global-option='--salt-root-dir=/path/to/your/virtualenv/' \
|
||||||
|
install -e ./salt # the path to the salt git clone from above
|
||||||
|
|
||||||
|
|
||||||
|
Instead of passing those two environmental variables, you can just pass a
|
||||||
|
single one which will trigger the other two:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
MIMIC_SALT_INSTALL=1 pip --global-option='--salt-root-dir=/path/to/your/virtualenv/' \
|
||||||
|
install -e ./salt # the path to the salt git clone from above
|
||||||
|
|
||||||
|
|
||||||
|
This last one will grant you an edditable salt installation with hardcoded
|
||||||
|
system paths and version information.
|
||||||
|
|
||||||
|
|
||||||
Installing Salt from the Python Package Index
|
Installing Salt from the Python Package Index
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -139,8 +139,8 @@ Install the following software:
|
||||||
Download the Prerequisite zip file for your CPU architecture from the
|
Download the Prerequisite zip file for your CPU architecture from the
|
||||||
SaltStack download site:
|
SaltStack download site:
|
||||||
|
|
||||||
* `Salt32.zip <http://docs.saltstack.com/downloads/windows-deps/Salt32.zip/>`_
|
* `Salt32.zip <http://repo.saltstack.com/windows/dependencies/Salt32.zip/>`_
|
||||||
* `Salt64.zip <http://docs.saltstack.com/downloads/windows-deps/Salt64.zip/>`_
|
* `Salt64.zip <http://repo.saltstack.com/windows/dependencies/Salt64.zip/>`_
|
||||||
|
|
||||||
These files contain all sofware required to build and develop salt. Unzip the
|
These files contain all sofware required to build and develop salt. Unzip the
|
||||||
contents of the file to ``C:\Salt-Dev\temp``.
|
contents of the file to ``C:\Salt-Dev\temp``.
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -73,7 +73,10 @@ start() {
|
||||||
RETVAL=1
|
RETVAL=1
|
||||||
else
|
else
|
||||||
daemon --pidfile=$PID_FILE --check $SERVICE $SALTAPI $CONFIG_ARGS
|
daemon --pidfile=$PID_FILE --check $SERVICE $SALTAPI $CONFIG_ARGS
|
||||||
RETVAL=0
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE
|
||||||
|
echo
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
|
@ -97,6 +100,10 @@ stop() {
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
killproc $PROCESS
|
killproc $PROCESS
|
||||||
|
RETVAL=$?
|
||||||
|
echo
|
||||||
|
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$SERVICE
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -64,6 +64,10 @@ start() {
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
daemon --check $SERVICE $SALTMASTER -d $MASTER_ARGS
|
daemon --check $SERVICE $SALTMASTER -d $MASTER_ARGS
|
||||||
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE
|
||||||
|
echo
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo
|
echo
|
||||||
|
@ -86,6 +90,10 @@ stop() {
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
killproc $PROCESS
|
killproc $PROCESS
|
||||||
|
RETVAL=$?
|
||||||
|
echo
|
||||||
|
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$SERVICE
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -68,7 +68,11 @@ start() {
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo -n "already running"
|
echo -n "already running"
|
||||||
else
|
else
|
||||||
daemon --check $SERVICE $SALTMINION -d $MINION_ARGS
|
daemon --check $SERVICE $SALTMINION -d $MINION_ARGS
|
||||||
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE
|
||||||
|
echo
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
|
@ -94,6 +98,7 @@ stop() {
|
||||||
else
|
else
|
||||||
killproc $PROCESS
|
killproc $PROCESS
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$SERVICE
|
||||||
# tidy up any rogue processes:
|
# tidy up any rogue processes:
|
||||||
PROCS=`ps -ef | grep "$SALTMINION" | grep -v grep | awk '{print $2}'`
|
PROCS=`ps -ef | grep "$SALTMINION" | grep -v grep | awk '{print $2}'`
|
||||||
if [ -n "$PROCS" ]; then
|
if [ -n "$PROCS" ]; then
|
||||||
|
|
|
@ -65,6 +65,10 @@ start() {
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
daemon --check $SERVICE $SALTSYNDIC -d $SYNDIC_ARGS
|
daemon --check $SERVICE $SALTSYNDIC -d $SYNDIC_ARGS
|
||||||
|
RETVAL=$?
|
||||||
|
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE
|
||||||
|
echo
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo
|
echo
|
||||||
|
@ -87,6 +91,10 @@ stop() {
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
killproc $PROCESS
|
killproc $PROCESS
|
||||||
|
RETVAL=$?
|
||||||
|
echo
|
||||||
|
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$SERVICE
|
||||||
|
return $RETVAL
|
||||||
fi
|
fi
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo
|
echo
|
||||||
|
|
|
@ -954,10 +954,10 @@ ARGS = {9}\n'''.format(self.minion_config,
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Execute shim
|
# Execute shim
|
||||||
ret = self.shell.exec_cmd('/bin/sh $HOME/{0}'.format(target_shim_file))
|
ret = self.shell.exec_cmd('/bin/sh \'$HOME/{0}\''.format(target_shim_file))
|
||||||
|
|
||||||
# Remove shim from target system
|
# Remove shim from target system
|
||||||
self.shell.exec_cmd('rm $HOME/{0}'.format(target_shim_file))
|
self.shell.exec_cmd('rm \'$HOME/{0}\''.format(target_shim_file))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -1654,7 +1654,6 @@ def request_instance(vm_=None, call=None):
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
rd_data = aws.query(rd_params,
|
rd_data = aws.query(rd_params,
|
||||||
return_root=True,
|
|
||||||
location=get_location(),
|
location=get_location(),
|
||||||
provider=get_provider(),
|
provider=get_provider(),
|
||||||
opts=__opts__,
|
opts=__opts__,
|
||||||
|
@ -2363,7 +2362,7 @@ def create(vm_=None, call=None):
|
||||||
'volumes': volumes,
|
'volumes': volumes,
|
||||||
'zone': ret['placement']['availabilityZone'],
|
'zone': ret['placement']['availabilityZone'],
|
||||||
'instance_id': ret['instanceId'],
|
'instance_id': ret['instanceId'],
|
||||||
'del_all_vols_on_destroy': vm_.get('set_del_all_vols_on_destroy', False)
|
'del_all_vols_on_destroy': vm_.get('del_all_vols_on_destroy', False)
|
||||||
},
|
},
|
||||||
call='action'
|
call='action'
|
||||||
)
|
)
|
||||||
|
@ -3780,38 +3779,52 @@ def delete_keypair(kwargs=None, call=None):
|
||||||
|
|
||||||
def create_snapshot(kwargs=None, call=None, wait_to_finish=False):
|
def create_snapshot(kwargs=None, call=None, wait_to_finish=False):
|
||||||
'''
|
'''
|
||||||
Create a snapshot
|
Create a snapshot.
|
||||||
|
|
||||||
|
volume_id
|
||||||
|
The ID of the Volume from which to create a snapshot.
|
||||||
|
|
||||||
|
description
|
||||||
|
The optional description of the snapshot.
|
||||||
|
|
||||||
|
CLI Exampe:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
salt-cloud -f create_snapshot my-ec2-config volume_id=vol-351d8826
|
||||||
|
salt-cloud -f create_snapshot my-ec2-config volume_id=vol-351d8826 \\
|
||||||
|
description="My Snapshot Description"
|
||||||
'''
|
'''
|
||||||
if call != 'function':
|
if call != 'function':
|
||||||
log.error(
|
raise SaltCloudSystemExit(
|
||||||
'The create_snapshot function must be called with -f '
|
'The create_snapshot function must be called with -f '
|
||||||
'or --function.'
|
'or --function.'
|
||||||
)
|
)
|
||||||
return False
|
|
||||||
|
|
||||||
if 'volume_id' not in kwargs:
|
if kwargs is None:
|
||||||
log.error('A volume_id must be specified to create a snapshot.')
|
kwargs = {}
|
||||||
return False
|
|
||||||
|
|
||||||
if 'description' not in kwargs:
|
volume_id = kwargs.get('volume_id', None)
|
||||||
kwargs['description'] = ''
|
description = kwargs.get('description', '')
|
||||||
|
|
||||||
params = {'Action': 'CreateSnapshot'}
|
if volume_id is None:
|
||||||
|
raise SaltCloudSystemExit(
|
||||||
|
'A volume_id must be specified to create a snapshot.'
|
||||||
|
)
|
||||||
|
|
||||||
if 'volume_id' in kwargs:
|
params = {'Action': 'CreateSnapshot',
|
||||||
params['VolumeId'] = kwargs['volume_id']
|
'VolumeId': volume_id,
|
||||||
|
'Description': description}
|
||||||
if 'description' in kwargs:
|
|
||||||
params['Description'] = kwargs['description']
|
|
||||||
|
|
||||||
log.debug(params)
|
log.debug(params)
|
||||||
|
|
||||||
data = aws.query(params,
|
data = aws.query(params,
|
||||||
return_url=True,
|
return_url=True,
|
||||||
|
return_root=True,
|
||||||
location=get_location(),
|
location=get_location(),
|
||||||
provider=get_provider(),
|
provider=get_provider(),
|
||||||
opts=__opts__,
|
opts=__opts__,
|
||||||
sigver='4')
|
sigver='4')[0]
|
||||||
|
|
||||||
r_data = {}
|
r_data = {}
|
||||||
for d in data:
|
for d in data:
|
||||||
|
@ -3827,7 +3840,7 @@ def create_snapshot(kwargs=None, call=None, wait_to_finish=False):
|
||||||
argument_being_watched='status',
|
argument_being_watched='status',
|
||||||
required_argument_response='completed')
|
required_argument_response='completed')
|
||||||
|
|
||||||
return data
|
return r_data
|
||||||
|
|
||||||
|
|
||||||
def delete_snapshot(kwargs=None, call=None):
|
def delete_snapshot(kwargs=None, call=None):
|
||||||
|
|
|
@ -348,7 +348,7 @@ class AutoKey(object):
|
||||||
autosign_dir = os.path.join(self.opts['pki_dir'], 'minions_autosign')
|
autosign_dir = os.path.join(self.opts['pki_dir'], 'minions_autosign')
|
||||||
|
|
||||||
# cleanup expired files
|
# cleanup expired files
|
||||||
expire_minutes = self.opts.get('autosign_expire_minutes', 10)
|
expire_minutes = self.opts.get('autosign_timeout', 120)
|
||||||
if expire_minutes > 0:
|
if expire_minutes > 0:
|
||||||
min_time = time.time() - (60 * int(expire_minutes))
|
min_time = time.time() - (60 * int(expire_minutes))
|
||||||
for root, dirs, filenames in os.walk(autosign_dir):
|
for root, dirs, filenames in os.walk(autosign_dir):
|
||||||
|
|
|
@ -1558,6 +1558,7 @@ class Minion(MinionBase):
|
||||||
del self.pub_channel
|
del self.pub_channel
|
||||||
self._connect_master_future = self.connect_master()
|
self._connect_master_future = self.connect_master()
|
||||||
self.block_until_connected() # TODO: remove
|
self.block_until_connected() # TODO: remove
|
||||||
|
self.functions, self.returners, self.function_errors = self._load_modules()
|
||||||
self._fire_master_minion_start()
|
self._fire_master_minion_start()
|
||||||
log.info('Minion is ready to receive requests!')
|
log.info('Minion is ready to receive requests!')
|
||||||
|
|
||||||
|
|
|
@ -231,12 +231,25 @@ def create_or_update_alarm(
|
||||||
if isinstance(ok_actions, string_types):
|
if isinstance(ok_actions, string_types):
|
||||||
ok_actions = ok_actions.split(",")
|
ok_actions = ok_actions.split(",")
|
||||||
|
|
||||||
# convert action names into ARN's
|
# convert provided action names into ARN's
|
||||||
alarm_actions = convert_to_arn(alarm_actions, region, key, keyid, profile)
|
if alarm_actions:
|
||||||
insufficient_data_actions = convert_to_arn(
|
alarm_actions = convert_to_arn(alarm_actions,
|
||||||
insufficient_data_actions, region, key, keyid, profile
|
region=region,
|
||||||
)
|
key=key,
|
||||||
ok_actions = convert_to_arn(ok_actions, region, key, keyid, profile)
|
keyid=keyid,
|
||||||
|
profile=profile)
|
||||||
|
if insufficient_data_actions:
|
||||||
|
insufficient_data_actions = convert_to_arn(insufficient_data_actions,
|
||||||
|
region=region,
|
||||||
|
key=key,
|
||||||
|
keyid=keyid,
|
||||||
|
profile=profile)
|
||||||
|
if ok_actions:
|
||||||
|
ok_actions = convert_to_arn(ok_actions,
|
||||||
|
region=region,
|
||||||
|
key=key,
|
||||||
|
keyid=keyid,
|
||||||
|
profile=profile)
|
||||||
|
|
||||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||||
|
|
||||||
|
|
|
@ -276,14 +276,20 @@ def list_tab(user):
|
||||||
ret['special'].append(dat)
|
ret['special'].append(dat)
|
||||||
elif line.startswith('#'):
|
elif line.startswith('#'):
|
||||||
# It's a comment! Catch it!
|
# It's a comment! Catch it!
|
||||||
comment = line.lstrip('# ')
|
comment_line = line.lstrip('# ')
|
||||||
|
|
||||||
# load the identifier if any
|
# load the identifier if any
|
||||||
if SALT_CRON_IDENTIFIER in comment:
|
if SALT_CRON_IDENTIFIER in comment_line:
|
||||||
parts = comment.split(SALT_CRON_IDENTIFIER)
|
parts = comment_line.split(SALT_CRON_IDENTIFIER)
|
||||||
comment = parts[0].rstrip()
|
comment_line = parts[0].rstrip()
|
||||||
# skip leading :
|
# skip leading :
|
||||||
if len(parts[1]) > 1:
|
if len(parts[1]) > 1:
|
||||||
identifier = parts[1][1:]
|
identifier = parts[1][1:]
|
||||||
|
|
||||||
|
if comment is None:
|
||||||
|
comment = comment_line
|
||||||
|
else:
|
||||||
|
comment += '\n' + comment_line
|
||||||
elif len(line.split()) > 5:
|
elif len(line.split()) > 5:
|
||||||
# Appears to be a standard cron line
|
# Appears to be a standard cron line
|
||||||
comps = line.split()
|
comps = line.split()
|
||||||
|
|
|
@ -26,6 +26,14 @@ from salt.exceptions import SaltInvocationError
|
||||||
|
|
||||||
# Import 3rd-party libs
|
# Import 3rd-party libs
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
|
try:
|
||||||
|
from shlex import quote as _cmd_quote # pylint: disable=E0611
|
||||||
|
except ImportError:
|
||||||
|
from pipes import quote as _cmd_quote
|
||||||
|
|
||||||
|
from salt.exceptions import (
|
||||||
|
SaltInvocationError
|
||||||
|
)
|
||||||
|
|
||||||
# Set up logging
|
# Set up logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -826,15 +834,15 @@ def trust_key(keyid=None,
|
||||||
if trust_level not in _VALID_TRUST_LEVELS:
|
if trust_level not in _VALID_TRUST_LEVELS:
|
||||||
return 'ERROR: Valid trust levels - {0}'.format(','.join(_VALID_TRUST_LEVELS))
|
return 'ERROR: Valid trust levels - {0}'.format(','.join(_VALID_TRUST_LEVELS))
|
||||||
|
|
||||||
cmd = 'echo {0}:{1} | {2} --import-ownertrust'.format(fingerprint,
|
cmd = 'echo {0}:{1} | {2} --import-ownertrust'.format(_cmd_quote(fingerprint),
|
||||||
NUM_TRUST_DICT[trust_level],
|
_cmd_quote(NUM_TRUST_DICT[trust_level]),
|
||||||
_check_gpg())
|
_cmd_quote(_check_gpg()))
|
||||||
_user = user
|
_user = user
|
||||||
if user == 'salt':
|
if user == 'salt':
|
||||||
homeDir = os.path.join(salt.syspaths.CONFIG_DIR, 'gpgkeys')
|
homeDir = os.path.join(salt.syspaths.CONFIG_DIR, 'gpgkeys')
|
||||||
cmd = '{0} --homedir {1}'.format(cmd, homeDir)
|
cmd = '{0} --homedir {1}'.format(cmd, homeDir)
|
||||||
_user = 'root'
|
_user = 'root'
|
||||||
res = __salt__['cmd.run_all'](cmd, runas=_user)
|
res = __salt__['cmd.run_all'](cmd, runas=_user, python_shell=True)
|
||||||
|
|
||||||
if not res['retcode'] == 0:
|
if not res['retcode'] == 0:
|
||||||
ret['res'] = False
|
ret['res'] = False
|
||||||
|
|
|
@ -51,6 +51,7 @@ Module for handling openstack keystone calls.
|
||||||
|
|
||||||
# Import Python libs
|
# Import Python libs
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
import logging
|
||||||
|
|
||||||
# Import Salt Libs
|
# Import Salt Libs
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
|
@ -66,6 +67,8 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
'''
|
'''
|
||||||
|
@ -707,7 +710,13 @@ def user_get(user_id=None, name=None, profile=None, **connection_args):
|
||||||
break
|
break
|
||||||
if not user_id:
|
if not user_id:
|
||||||
return {'Error': 'Unable to resolve user id'}
|
return {'Error': 'Unable to resolve user id'}
|
||||||
user = kstone.users.get(user_id)
|
try:
|
||||||
|
user = kstone.users.get(user_id)
|
||||||
|
except keystoneclient.exceptions.NotFound:
|
||||||
|
msg = 'Could not find user \'{0}\''.format(user_id)
|
||||||
|
log.error(msg)
|
||||||
|
return {'Error': msg}
|
||||||
|
|
||||||
ret[user.name] = {'id': user.id,
|
ret[user.name] = {'id': user.id,
|
||||||
'name': user.name,
|
'name': user.name,
|
||||||
'email': user.email,
|
'email': user.email,
|
||||||
|
|
|
@ -391,7 +391,7 @@ def vgremove(vgname):
|
||||||
salt mymachine lvm.vgremove vgname
|
salt mymachine lvm.vgremove vgname
|
||||||
salt mymachine lvm.vgremove vgname force=True
|
salt mymachine lvm.vgremove vgname force=True
|
||||||
'''
|
'''
|
||||||
cmd = ['vgremove' '-f', vgname]
|
cmd = ['vgremove', '-f', vgname]
|
||||||
out = __salt__['cmd.run'](cmd, python_shell=False)
|
out = __salt__['cmd.run'](cmd, python_shell=False)
|
||||||
return out.strip()
|
return out.strip()
|
||||||
|
|
||||||
|
|
|
@ -130,3 +130,23 @@ def chgid(name, gid):
|
||||||
if post_gid != pre_gid:
|
if post_gid != pre_gid:
|
||||||
return post_gid == gid
|
return post_gid == gid
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def members(name, members_list):
|
||||||
|
'''
|
||||||
|
Replaces members of the group with a provided list.
|
||||||
|
|
||||||
|
.. versionadded:: 2015.5.4
|
||||||
|
|
||||||
|
CLI Example:
|
||||||
|
|
||||||
|
salt '*' group.members foo 'user1,user2,user3,...'
|
||||||
|
|
||||||
|
Replaces a membership list for a local group 'foo'.
|
||||||
|
foo:x:1234:user1,user2,user3,...
|
||||||
|
'''
|
||||||
|
|
||||||
|
retcode = __salt__['cmd.retcode']('pw groupmod {0} -M {1}'.format(
|
||||||
|
name, members_list), python_shell=False)
|
||||||
|
|
||||||
|
return not retcode
|
||||||
|
|
|
@ -9,8 +9,9 @@ import copy
|
||||||
import logging
|
import logging
|
||||||
try:
|
try:
|
||||||
import pwd
|
import pwd
|
||||||
|
HAS_PWD = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
HAS_PWD = False
|
||||||
|
|
||||||
# Import 3rd party libs
|
# Import 3rd party libs
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
|
@ -29,7 +30,9 @@ def __virtual__():
|
||||||
'''
|
'''
|
||||||
Set the user module if the kernel is FreeBSD
|
Set the user module if the kernel is FreeBSD
|
||||||
'''
|
'''
|
||||||
return __virtualname__ if __grains__['kernel'] == 'FreeBSD' else False
|
if HAS_PWD and __grains__['kernel'] == 'FreeBSD':
|
||||||
|
return __virtualname__
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _get_gecos(name):
|
def _get_gecos(name):
|
||||||
|
|
|
@ -1,29 +1,36 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
'''
|
||||||
Manage the registry on Windows.
|
===========================
|
||||||
|
Manage the Windows registry
|
||||||
|
===========================
|
||||||
|
|
||||||
The read_key and set_key functions will be updated in Boron to reflect proper
|
The read_key and set_key functions will be updated in Boron to reflect proper
|
||||||
registry usage. The registry has three main components. Hives, Keys, and Values.
|
registry usage. The registry has three main components. Hives, Keys, and Values.
|
||||||
|
|
||||||
### Hives
|
-----
|
||||||
|
Hives
|
||||||
|
-----
|
||||||
Hives are the main sections of the registry and all begin with the word HKEY.
|
Hives are the main sections of the registry and all begin with the word HKEY.
|
||||||
- HKEY_LOCAL_MACHINE
|
- HKEY_LOCAL_MACHINE
|
||||||
- HKEY_CURRENT_USER
|
- HKEY_CURRENT_USER
|
||||||
- HKEY_USER
|
- HKEY_USER
|
||||||
|
|
||||||
### Keys
|
----
|
||||||
|
Keys
|
||||||
|
----
|
||||||
Keys are the folders in the registry. Keys can have many nested subkeys. Keys
|
Keys are the folders in the registry. Keys can have many nested subkeys. Keys
|
||||||
can have a value assigned to them under the (Default)
|
can have a value assigned to them under the (Default)
|
||||||
|
|
||||||
### Values
|
-----------------
|
||||||
Values are name/data pairs. There can be many values in a key. The (Default)
|
Values or Entries
|
||||||
value corresponds to the Key, the rest are their own value pairs.
|
-----------------
|
||||||
|
Values/Entries are name/data pairs. There can be many values in a key. The
|
||||||
|
(Default) value corresponds to the Key, the rest are their own value pairs.
|
||||||
|
|
||||||
:depends: - winreg Python module
|
:depends: - winreg Python module
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# TODO: Figure out the exceptions _winreg can raise and properly catch
|
# TODO: Figure out the exceptions _winreg can raise and properly catch them
|
||||||
# them instead of a bare except that catches any exception at all
|
|
||||||
|
|
||||||
# Import python libs
|
# Import python libs
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
@ -142,44 +149,35 @@ def read_key(hkey, path, key=None):
|
||||||
key=path,
|
key=path,
|
||||||
vname=key)
|
vname=key)
|
||||||
|
|
||||||
registry = Registry()
|
return read_value(hive=hkey, key=path)
|
||||||
hive = registry.hkeys[hkey]
|
|
||||||
|
|
||||||
try:
|
|
||||||
value = _winreg.QueryValue(hive, path)
|
|
||||||
if value:
|
|
||||||
ret['vdata'] = value
|
|
||||||
else:
|
|
||||||
ret['vdata'] = None
|
|
||||||
ret['comment'] = 'Empty Value'
|
|
||||||
except WindowsError as exc: # pylint: disable=E0602
|
|
||||||
log.debug(exc)
|
|
||||||
ret['comment'] = '{0}'.format(exc)
|
|
||||||
ret['success'] = False
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def read_value(hive, key, vname=None):
|
def read_value(hive, key, vname=None):
|
||||||
r'''
|
r'''
|
||||||
Reads a registry value or the default value for a key.
|
Reads a registry value entry or the default value for a key.
|
||||||
|
|
||||||
:param hive: string
|
:param str hive:
|
||||||
The name of the hive. Can be one of the following
|
The name of the hive. Can be one of the following
|
||||||
- HKEY_LOCAL_MACHINE or HKLM
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
- HKEY_CURRENT_USER or HKCU
|
- HKEY_CURRENT_USER or HKCU
|
||||||
- HKEY_USER or HKU
|
- HKEY_USER or HKU
|
||||||
|
|
||||||
:param key: string
|
:param str key:
|
||||||
The key (looks like a path) to the value name.
|
The key (looks like a path) to the value name.
|
||||||
|
|
||||||
:param vname: string
|
:param str vname:
|
||||||
The value name. These are the individual name/data pairs under the key. If
|
The value name. These are the individual name/data pairs under the key.
|
||||||
not passed, the key (Default) value will be returned
|
If not passed, the key (Default) value will be returned
|
||||||
|
|
||||||
:return: dict
|
:return:
|
||||||
A dictionary containing the passed settings as well as the value_data if
|
A dictionary containing the passed settings as well as the value_data if
|
||||||
successful. If unsuccessful, sets success to False
|
successful. If unsuccessful, sets success to False
|
||||||
|
|
||||||
|
If vname is not passed:
|
||||||
|
- Returns the first unnamed value (Default) as a string.
|
||||||
|
- Returns none if first unnamed value is empty.
|
||||||
|
- Returns False if key not found.
|
||||||
|
:rtype: dict
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
|
@ -205,9 +203,9 @@ def read_value(hive, key, vname=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handle = _winreg.OpenKey(hive, key)
|
handle = _winreg.OpenKey(hive, key)
|
||||||
value, vtype = _winreg.QueryValueEx(handle, vname)
|
vdata, vtype = _winreg.QueryValueEx(handle, vname)
|
||||||
if value:
|
if vdata:
|
||||||
ret['vdata'] = value
|
ret['vdata'] = vdata
|
||||||
ret['vtype'] = registry.vtype_reverse[vtype]
|
ret['vtype'] = registry.vtype_reverse[vtype]
|
||||||
else:
|
else:
|
||||||
ret['comment'] = 'Empty Value'
|
ret['comment'] = 'Empty Value'
|
||||||
|
@ -257,53 +255,45 @@ def set_key(hkey, path, value, key=None, vtype='REG_DWORD', reflection=True):
|
||||||
vdata=value,
|
vdata=value,
|
||||||
vtype=vtype)
|
vtype=vtype)
|
||||||
|
|
||||||
registry = Registry()
|
return set_value(hive=hkey, key=path, vdata=value, vtype=vtype)
|
||||||
hive = registry.hkeys[hkey]
|
|
||||||
vtype = registry.vtype['REG_SZ']
|
|
||||||
|
|
||||||
try:
|
|
||||||
_winreg.SetValue(hive, path, vtype, value)
|
|
||||||
return True
|
|
||||||
except WindowsError as exc: # pylint: disable=E0602
|
|
||||||
log.error(exc)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def set_value(hive, key, vname=None, vdata=None, vtype='REG_SZ', reflection=True):
|
def set_value(hive, key, vname=None, vdata=None, vtype='REG_SZ', reflection=True):
|
||||||
'''
|
'''
|
||||||
Sets a registry value.
|
Sets a registry value entry or the default value for a key.
|
||||||
|
|
||||||
:param hive: string
|
:param str hive:
|
||||||
The name of the hive. Can be one of the following
|
The name of the hive. Can be one of the following
|
||||||
- HKEY_LOCAL_MACHINE or HKLM
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
- HKEY_CURRENT_USER or HKCU
|
- HKEY_CURRENT_USER or HKCU
|
||||||
- HKEY_USER or HKU
|
- HKEY_USER or HKU
|
||||||
|
|
||||||
:param key: string
|
:param str key:
|
||||||
The key (looks like a path) to the value name.
|
The key (looks like a path) to the value name.
|
||||||
|
|
||||||
:param vname: string
|
:param str vname:
|
||||||
The value name. These are the individual name/data pairs under the key. If
|
The value name. These are the individual name/data pairs under the key.
|
||||||
not passed, the key (Default) value will be set.
|
If not passed, the key (Default) value will be set.
|
||||||
|
|
||||||
:param vdata: string
|
:param str vdata:
|
||||||
The value data to be set.
|
The value data to be set.
|
||||||
|
|
||||||
:param vtype: string
|
:param str vtype:
|
||||||
The value type. Can be one of the following:
|
The value type. Can be one of the following:
|
||||||
- REG_BINARY
|
- REG_BINARY
|
||||||
- REG_DWORD
|
- REG_DWORD
|
||||||
- REG_EXPAND_SZ
|
- REG_EXPAND_SZ
|
||||||
- REG_MULTI_SZ
|
- REG_MULTI_SZ
|
||||||
- REG_SZ
|
- REG_SZ
|
||||||
|
|
||||||
:param reflection: boolean
|
:param bool reflection:
|
||||||
A boolean value indicating that the value should also be set in the
|
A boolean value indicating that the value should also be set in the
|
||||||
Wow6432Node portion of the registry. Only applies to 64 bit Windows. This
|
Wow6432Node portion of the registry. Only applies to 64 bit Windows.
|
||||||
setting is ignored for 32 bit Windows.
|
This setting is ignored for 32 bit Windows.
|
||||||
|
|
||||||
:return: boolean
|
:return:
|
||||||
Returns True if successful, False if not
|
Returns True if successful, False if not
|
||||||
|
:rtype: bool
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
|
@ -321,7 +311,7 @@ def set_value(hive, key, vname=None, vdata=None, vtype='REG_SZ', reflection=True
|
||||||
_winreg.SetValueEx(handle, vname, 0, vtype, vdata)
|
_winreg.SetValueEx(handle, vname, 0, vtype, vdata)
|
||||||
_winreg.CloseKey(handle)
|
_winreg.CloseKey(handle)
|
||||||
return True
|
return True
|
||||||
except WindowsError as exc: # pylint: disable=E0602
|
except (WindowsError, ValueError) as exc: # pylint: disable=E0602
|
||||||
log.error(exc)
|
log.error(exc)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -353,7 +343,7 @@ def create_key(hkey, path, key=None, value=None, reflection=True):
|
||||||
salt '*' reg.create_key HKEY_CURRENT_USER 'SOFTWARE\\Salt' 'version' '0.97'
|
salt '*' reg.create_key HKEY_CURRENT_USER 'SOFTWARE\\Salt' 'version' '0.97'
|
||||||
'''
|
'''
|
||||||
if key: # This if statement will be removed in Boron
|
if key: # This if statement will be removed in Boron
|
||||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry '
|
salt.utils.warn_until('Boron', 'Use reg.set_value to create a registry '
|
||||||
'value. This functionality will be '
|
'value. This functionality will be '
|
||||||
'removed in Salt Boron')
|
'removed in Salt Boron')
|
||||||
return set_value(hive=hkey,
|
return set_value(hive=hkey,
|
||||||
|
@ -362,21 +352,10 @@ def create_key(hkey, path, key=None, value=None, reflection=True):
|
||||||
vdata=value,
|
vdata=value,
|
||||||
vtype='REG_SZ')
|
vtype='REG_SZ')
|
||||||
|
|
||||||
registry = Registry()
|
return set_value(hive=hkey, key=path)
|
||||||
hive = registry.hkeys[hkey]
|
|
||||||
key = path
|
|
||||||
access_mask = registry.reflection_mask[reflection]
|
|
||||||
|
|
||||||
try:
|
|
||||||
handle = _winreg.CreateKeyEx(hive, key, 0, access_mask)
|
|
||||||
_winreg.CloseKey(handle)
|
|
||||||
return True
|
|
||||||
except WindowsError as exc: # pylint: disable=E0602
|
|
||||||
log.error(exc)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def delete_key(hkey, path, key=None, reflection=True):
|
def delete_key(hkey, path, key=None, reflection=True, force=False):
|
||||||
'''
|
'''
|
||||||
*** Incorrect Usage ***
|
*** Incorrect Usage ***
|
||||||
The name of this function is misleading and will be changed to reflect
|
The name of this function is misleading and will be changed to reflect
|
||||||
|
@ -396,29 +375,62 @@ def delete_key(hkey, path, key=None, reflection=True):
|
||||||
|
|
||||||
Delete a registry key
|
Delete a registry key
|
||||||
|
|
||||||
Note: This cannot delete a key with subkeys
|
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
salt '*' reg.delete_key HKEY_CURRENT_USER 'SOFTWARE\\Salt'
|
salt '*' reg.delete_key HKEY_CURRENT_USER 'SOFTWARE\\Salt'
|
||||||
|
|
||||||
|
:param str hkey: (will be changed to hive)
|
||||||
|
The name of the hive. Can be one of the following
|
||||||
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
|
- HKEY_CURRENT_USER or HKCU
|
||||||
|
- HKEY_USER or HKU
|
||||||
|
|
||||||
|
:param str path: (will be changed to key)
|
||||||
|
The key (looks like a path) to remove.
|
||||||
|
|
||||||
|
:param str key: (used incorrectly)
|
||||||
|
Will be removed in Boron
|
||||||
|
|
||||||
|
:param bool reflection:
|
||||||
|
A boolean value indicating that the value should also be removed from
|
||||||
|
the Wow6432Node portion of the registry. Only applies to 64 bit Windows.
|
||||||
|
This setting is ignored for 32 bit Windows.
|
||||||
|
|
||||||
|
Only applies to delete value. If the key parameter is passed, this
|
||||||
|
function calls delete_value instead. Will be changed in Boron.
|
||||||
|
|
||||||
|
:param bool force:
|
||||||
|
A boolean value indicating that all subkeys should be removed as well.
|
||||||
|
If this is set to False (default) and there are subkeys, the delete_key
|
||||||
|
function will fail.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
Returns True if successful, False if not
|
||||||
|
If force=True, the results of delete_key_recursive are returned.
|
||||||
|
:rtype: bool
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if key: # This if statement will be removed in Boron
|
if key: # This if statement will be removed in Boron
|
||||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry '
|
salt.utils.warn_until('Boron',
|
||||||
'value. This functionality will be '
|
'Variable names will be changed to match Windows '
|
||||||
'removed in Salt Boron')
|
'Registry terminology. These changes will be '
|
||||||
|
'made in Boron')
|
||||||
return delete_value(hive=hkey,
|
return delete_value(hive=hkey,
|
||||||
key=path,
|
key=path,
|
||||||
vname=key,
|
vname=key,
|
||||||
reflection=reflection)
|
reflection=reflection)
|
||||||
|
|
||||||
|
if force:
|
||||||
|
return delete_key_recursive(hkey, path)
|
||||||
|
|
||||||
registry = Registry()
|
registry = Registry()
|
||||||
hive = registry.hkeys[hkey]
|
hive = registry.hkeys[hkey]
|
||||||
key = path
|
key = path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Can't use delete_value to delete a key
|
||||||
_winreg.DeleteKey(hive, key)
|
_winreg.DeleteKey(hive, key)
|
||||||
return True
|
return True
|
||||||
except WindowsError as exc: # pylint: disable=E0602
|
except WindowsError as exc: # pylint: disable=E0602
|
||||||
|
@ -426,30 +438,102 @@ def delete_key(hkey, path, key=None, reflection=True):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def delete_key_recursive(hive, key):
|
||||||
|
'''
|
||||||
|
.. versionadded:: 2015.5.4
|
||||||
|
|
||||||
|
Delete a registry key to include all subkeys.
|
||||||
|
|
||||||
|
:param hive:
|
||||||
|
The name of the hive. Can be one of the following
|
||||||
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
|
- HKEY_CURRENT_USER or HKCU
|
||||||
|
- HKEY_USER or HKU
|
||||||
|
|
||||||
|
:param key:
|
||||||
|
The key to remove (looks like a path)
|
||||||
|
|
||||||
|
:return:
|
||||||
|
A dictionary listing the keys that deleted successfully as well as those
|
||||||
|
that failed to delete.
|
||||||
|
:rtype: dict
|
||||||
|
'''
|
||||||
|
# Functions for traversing the registry tree
|
||||||
|
def subkeys(key):
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
subkey = _winreg.EnumKey(key, i)
|
||||||
|
yield subkey
|
||||||
|
i += 1
|
||||||
|
except WindowsError: # pylint: disable=E0602
|
||||||
|
break
|
||||||
|
|
||||||
|
def traverse_registry_tree(hkey, keypath, ret):
|
||||||
|
key = _winreg.OpenKey(hkey, keypath, 0, _winreg.KEY_READ)
|
||||||
|
for subkeyname in subkeys(key):
|
||||||
|
subkeypath = r'{0}\{1}'.format(keypath, subkeyname)
|
||||||
|
ret = traverse_registry_tree(hkey, subkeypath, ret)
|
||||||
|
ret.append('{0}'.format(subkeypath))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# Instantiate the registry object
|
||||||
|
registry = Registry()
|
||||||
|
hkey = registry.hkeys[hive]
|
||||||
|
keypath = key
|
||||||
|
|
||||||
|
# Get a reverse list of registry keys to be deleted
|
||||||
|
key_list = []
|
||||||
|
key_list = traverse_registry_tree(hkey, keypath, key_list)
|
||||||
|
|
||||||
|
ret = {'Deleted': [],
|
||||||
|
'Failed': []}
|
||||||
|
|
||||||
|
# Delete all subkeys
|
||||||
|
for keypath in key_list:
|
||||||
|
try:
|
||||||
|
_winreg.DeleteKey(hkey, keypath)
|
||||||
|
ret['Deleted'].append(r'{0}\{1}'.format(hive, keypath))
|
||||||
|
except WindowsError as exc: # pylint: disable=E0602
|
||||||
|
log.error(exc)
|
||||||
|
ret['Failed'].append(r'{0}\{1} {2}'.format(hive, key, exc))
|
||||||
|
|
||||||
|
# Delete the key now that all the subkeys are deleted
|
||||||
|
try:
|
||||||
|
_winreg.DeleteKey(hkey, key)
|
||||||
|
ret['Deleted'].append(r'{0}\{1}'.format(hive, key))
|
||||||
|
except WindowsError as exc: # pylint: disable=E0602
|
||||||
|
log.error(exc)
|
||||||
|
ret['Failed'].append(r'{0}\{1} {2}'.format(hive, key, exc))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def delete_value(hive, key, vname=None, reflection=True):
|
def delete_value(hive, key, vname=None, reflection=True):
|
||||||
'''
|
'''
|
||||||
Deletes a registry value.
|
Delete a registry value entry or the default value for a key.
|
||||||
|
|
||||||
:param hive: string
|
:param str hive:
|
||||||
The name of the hive. Can be one of the following
|
The name of the hive. Can be one of the following
|
||||||
- HKEY_LOCAL_MACHINE or HKLM
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
- HKEY_CURRENT_USER or HKCU
|
- HKEY_CURRENT_USER or HKCU
|
||||||
- HKEY_USER or HKU
|
- HKEY_USER or HKU
|
||||||
|
|
||||||
:param key: string
|
:param str key:
|
||||||
The key (looks like a path) to the value name.
|
The key (looks like a path) to the value name.
|
||||||
|
|
||||||
:param vname: string
|
:param str vname:
|
||||||
The value name. These are the individual name/data pairs under the key. If
|
The value name. These are the individual name/data pairs under the key.
|
||||||
not passed, the key (Default) value will be deleted.
|
If not passed, the key (Default) value will be deleted.
|
||||||
|
|
||||||
:param reflection: boolean
|
:param bool reflection:
|
||||||
A boolean value indicating that the value should also be set in the
|
A boolean value indicating that the value should also be set in the
|
||||||
Wow6432Node portion of the registry. Only applies to 64 bit Windows. This
|
Wow6432Node portion of the registry. Only applies to 64 bit Windows.
|
||||||
setting is ignored for 32 bit Windows.
|
This setting is ignored for 32 bit Windows.
|
||||||
|
|
||||||
:return: boolean
|
:return:
|
||||||
Returns True if successful, False if not
|
Returns True if successful, False if not
|
||||||
|
:rtype: bool
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,11 @@ def list_(show_all=False, where=None, return_yaml=True):
|
||||||
del schedule[job]
|
del schedule[job]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# if enabled is not included in the job,
|
||||||
|
# assume job is enabled.
|
||||||
|
if 'enabled' not in schedule[job]:
|
||||||
|
schedule[job]['enabled'] = True
|
||||||
|
|
||||||
for item in pycopy.copy(schedule[job]):
|
for item in pycopy.copy(schedule[job]):
|
||||||
if item not in SCHEDULE_CONF:
|
if item not in SCHEDULE_CONF:
|
||||||
del schedule[job][item]
|
del schedule[job][item]
|
||||||
|
|
|
@ -9,8 +9,9 @@ import re
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pwd
|
import pwd
|
||||||
|
HAS_PWD = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
HAS_PWD = False
|
||||||
import logging
|
import logging
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
@ -32,10 +33,9 @@ __virtualname__ = 'user'
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
'''
|
'''
|
||||||
Set the user module if the kernel is Linux, OpenBSD or NetBSD
|
Set the user module if the kernel is Linux, OpenBSD or NetBSD
|
||||||
and remove some of the functionality on OS X
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if __grains__['kernel'] in ('Linux', 'OpenBSD', 'NetBSD'):
|
if HAS_PWD and __grains__['kernel'] in ('Linux', 'OpenBSD', 'NetBSD'):
|
||||||
return __virtualname__
|
return __virtualname__
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,11 @@ Overriding the alarm values on the resource:
|
||||||
attributes:
|
attributes:
|
||||||
threshold: 2.0
|
threshold: 2.0
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# Import Python Libs
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
# Import Salt Libs
|
||||||
import salt.utils.dictupdate as dictupdate
|
import salt.utils.dictupdate as dictupdate
|
||||||
from salt.exceptions import SaltInvocationError
|
from salt.exceptions import SaltInvocationError
|
||||||
import salt.ext.six as six
|
import salt.ext.six as six
|
||||||
|
@ -307,13 +311,17 @@ def present(
|
||||||
ret['result'] = _ret['result']
|
ret['result'] = _ret['result']
|
||||||
if ret['result'] is False:
|
if ret['result'] is False:
|
||||||
return ret
|
return ret
|
||||||
_ret = _attributes_present(name, attributes, region, key, keyid, profile)
|
|
||||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
if attributes:
|
||||||
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
_ret = _attributes_present(name, attributes, region, key, keyid, profile)
|
||||||
if not _ret['result']:
|
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||||
ret['result'] = _ret['result']
|
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
||||||
if ret['result'] is False:
|
|
||||||
return ret
|
if not _ret['result']:
|
||||||
|
ret['result'] = _ret['result']
|
||||||
|
if ret['result'] is False:
|
||||||
|
return ret
|
||||||
|
|
||||||
_ret = _health_check_present(name, health_check, region, key, keyid,
|
_ret = _health_check_present(name, health_check, region, key, keyid,
|
||||||
profile)
|
profile)
|
||||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||||
|
|
|
@ -125,8 +125,7 @@ from salt.ext.six import string_types
|
||||||
import salt.utils
|
import salt.utils
|
||||||
from salt.modules.cron import (
|
from salt.modules.cron import (
|
||||||
_needs_change,
|
_needs_change,
|
||||||
_cron_matched,
|
_cron_matched
|
||||||
SALT_CRON_NO_IDENTIFIER
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,7 +216,7 @@ def present(name,
|
||||||
month='*',
|
month='*',
|
||||||
dayweek='*',
|
dayweek='*',
|
||||||
comment=None,
|
comment=None,
|
||||||
identifier=None):
|
identifier=False):
|
||||||
'''
|
'''
|
||||||
Verifies that the specified cron job is present for the specified user.
|
Verifies that the specified cron job is present for the specified user.
|
||||||
For more advanced information about what exactly can be set in the cron
|
For more advanced information about what exactly can be set in the cron
|
||||||
|
@ -257,8 +256,8 @@ def present(name,
|
||||||
edits. This defaults to the state id
|
edits. This defaults to the state id
|
||||||
'''
|
'''
|
||||||
name = ' '.join(name.strip().split())
|
name = ' '.join(name.strip().split())
|
||||||
if not identifier:
|
if identifier is False:
|
||||||
identifier = SALT_CRON_NO_IDENTIFIER
|
identifier = name
|
||||||
ret = {'changes': {},
|
ret = {'changes': {},
|
||||||
'comment': '',
|
'comment': '',
|
||||||
'name': name,
|
'name': name,
|
||||||
|
@ -313,7 +312,7 @@ def present(name,
|
||||||
|
|
||||||
def absent(name,
|
def absent(name,
|
||||||
user='root',
|
user='root',
|
||||||
identifier=None,
|
identifier=False,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
'''
|
'''
|
||||||
Verifies that the specified cron job is absent for the specified user; only
|
Verifies that the specified cron job is absent for the specified user; only
|
||||||
|
@ -335,8 +334,8 @@ def absent(name,
|
||||||
### of unsupported arguments will result in a traceback.
|
### of unsupported arguments will result in a traceback.
|
||||||
|
|
||||||
name = ' '.join(name.strip().split())
|
name = ' '.join(name.strip().split())
|
||||||
if not identifier:
|
if identifier is False:
|
||||||
identifier = SALT_CRON_NO_IDENTIFIER
|
identifier = name
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'result': True,
|
'result': True,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
|
|
|
@ -220,8 +220,7 @@ def absent(name, destructive=False):
|
||||||
'changes': {},
|
'changes': {},
|
||||||
'result': True,
|
'result': True,
|
||||||
'comment': ''}
|
'comment': ''}
|
||||||
grain = __grains__.get(name)
|
if name in __grains__:
|
||||||
if grain:
|
|
||||||
if __opts__['test']:
|
if __opts__['test']:
|
||||||
ret['result'] = None
|
ret['result'] = None
|
||||||
if destructive is True:
|
if destructive is True:
|
||||||
|
|
|
@ -8,10 +8,12 @@ Manage OpenStack configuration file settings.
|
||||||
:platform: linux
|
:platform: linux
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# Import Python Libs
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
# Import salt libs
|
# Import Salt Libs
|
||||||
import salt.exceptions
|
from salt.exceptions import CommandExecutionError
|
||||||
|
|
||||||
|
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
|
@ -48,18 +50,30 @@ def present(name, filename, section, value, parameter=None):
|
||||||
if parameter is None:
|
if parameter is None:
|
||||||
parameter = name
|
parameter = name
|
||||||
|
|
||||||
|
ret = {'name': name,
|
||||||
|
'changes': {},
|
||||||
|
'result': False,
|
||||||
|
'comment': ''}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_value = __salt__['openstack_config.get'](filename=filename,
|
old_value = __salt__['openstack_config.get'](filename=filename,
|
||||||
section=section,
|
section=section,
|
||||||
parameter=parameter)
|
parameter=parameter)
|
||||||
|
|
||||||
if old_value == value:
|
if old_value == value:
|
||||||
return {'name': name,
|
ret['result'] = True
|
||||||
'changes': {},
|
ret['comment'] = 'The value is already set to the correct value'
|
||||||
'result': True,
|
return ret
|
||||||
'comment': 'The value is already set to the correct value'}
|
|
||||||
|
|
||||||
except salt.exceptions.CommandExecutionError as e:
|
if __opts__['test']:
|
||||||
|
ret['result'] = None
|
||||||
|
ret['comment'] = 'Value \'{0}\' is set to be changed to \'{1}\'.'.format(
|
||||||
|
old_value,
|
||||||
|
value
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
except CommandExecutionError as e:
|
||||||
if not str(e).lower().startswith('parameter not found:'):
|
if not str(e).lower().startswith('parameter not found:'):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@ -68,10 +82,11 @@ def present(name, filename, section, value, parameter=None):
|
||||||
parameter=parameter,
|
parameter=parameter,
|
||||||
value=value)
|
value=value)
|
||||||
|
|
||||||
return {'name': name,
|
ret['changes'] = {'Value': 'Updated'}
|
||||||
'changes': {'Value': 'Updated'},
|
ret['result'] = True
|
||||||
'result': True,
|
ret['comment'] = 'The value has been updated'
|
||||||
'comment': 'The value has been updated'}
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def absent(name, filename, section, parameter=None):
|
def absent(name, filename, section, parameter=None):
|
||||||
|
@ -92,23 +107,35 @@ def absent(name, filename, section, parameter=None):
|
||||||
if parameter is None:
|
if parameter is None:
|
||||||
parameter = name
|
parameter = name
|
||||||
|
|
||||||
|
ret = {'name': name,
|
||||||
|
'changes': {},
|
||||||
|
'result': False,
|
||||||
|
'comment': ''}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
old_value = __salt__['openstack_config.get'](filename=filename,
|
old_value = __salt__['openstack_config.get'](filename=filename,
|
||||||
section=section,
|
section=section,
|
||||||
parameter=parameter)
|
parameter=parameter)
|
||||||
except salt.exceptions.CommandExecutionError as e:
|
except CommandExecutionError as e:
|
||||||
if str(e).lower().startswith('parameter not found:'):
|
if str(e).lower().startswith('parameter not found:'):
|
||||||
return {'name': name,
|
ret['result'] = True
|
||||||
'changes': {},
|
ret['comment'] = 'The value is already absent'
|
||||||
'result': True,
|
return ret
|
||||||
'comment': 'The value is already absent'}
|
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
if __opts__['test']:
|
||||||
|
ret['result'] = None
|
||||||
|
ret['comment'] = 'Value \'{0}\' is set to be deleted.'.format(
|
||||||
|
old_value
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
__salt__['openstack_config.delete'](filename=filename,
|
__salt__['openstack_config.delete'](filename=filename,
|
||||||
section=section,
|
section=section,
|
||||||
parameter=parameter)
|
parameter=parameter)
|
||||||
|
|
||||||
return {'name': name,
|
ret['changes'] = {'Value': 'Deleted'}
|
||||||
'changes': {'Value': 'Deleted'},
|
ret['result'] = True
|
||||||
'result': True,
|
ret['comment'] = 'The value has been deleted'
|
||||||
'comment': 'The value has been deleted'}
|
|
||||||
|
return ret
|
||||||
|
|
|
@ -59,7 +59,7 @@ def __virtual__():
|
||||||
'''
|
'''
|
||||||
Only load if the pip module is available in __salt__
|
Only load if the pip module is available in __salt__
|
||||||
'''
|
'''
|
||||||
if HAS_PIP and 'pip.list' in __salt__:
|
if 'pip.list' in __salt__:
|
||||||
return __virtualname__
|
return __virtualname__
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -100,6 +100,16 @@ def _check_pkg_version_format(pkg):
|
||||||
|
|
||||||
ret = {'result': False, 'comment': None,
|
ret = {'result': False, 'comment': None,
|
||||||
'prefix': None, 'version_spec': None}
|
'prefix': None, 'version_spec': None}
|
||||||
|
|
||||||
|
if not HAS_PIP:
|
||||||
|
ret['comment'] = (
|
||||||
|
'An importable pip module is required but could not be found on '
|
||||||
|
'your system. This usually means that the system''s pip package '
|
||||||
|
'is not installed properly.'
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
from_vcs = False
|
from_vcs = False
|
||||||
try:
|
try:
|
||||||
# Get the requirement object from the pip library
|
# Get the requirement object from the pip library
|
||||||
|
|
|
@ -42,14 +42,14 @@ def __virtual__():
|
||||||
return salt.utils.which('rabbitmqctl') is not None
|
return salt.utils.which('rabbitmqctl') is not None
|
||||||
|
|
||||||
|
|
||||||
def _check_perms_changes(name, newperms):
|
def _check_perms_changes(name, newperms, runas=None):
|
||||||
'''
|
'''
|
||||||
Whether Rabbitmq user's permissions need to be changed
|
Whether Rabbitmq user's permissions need to be changed
|
||||||
'''
|
'''
|
||||||
if not newperms:
|
if not newperms:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
existing_perms = __salt__['rabbitmq.list_user_permissions'](name)
|
existing_perms = __salt__['rabbitmq.list_user_permissions'](name, runas=runas)
|
||||||
|
|
||||||
perm_need_change = False
|
perm_need_change = False
|
||||||
for vhost_perms in newperms:
|
for vhost_perms in newperms:
|
||||||
|
@ -63,14 +63,14 @@ def _check_perms_changes(name, newperms):
|
||||||
return perm_need_change
|
return perm_need_change
|
||||||
|
|
||||||
|
|
||||||
def _check_tags_changes(name, newtags):
|
def _check_tags_changes(name, newtags, runas=None):
|
||||||
'''
|
'''
|
||||||
Whether Rabbitmq user's tags need to be changed
|
Whether Rabbitmq user's tags need to be changed
|
||||||
'''
|
'''
|
||||||
if newtags:
|
if newtags:
|
||||||
if isinstance(newtags, str):
|
if isinstance(newtags, str):
|
||||||
newtags = newtags.split()
|
newtags = newtags.split()
|
||||||
return __salt__['rabbitmq.list_users']()[name] - set(newtags)
|
return __salt__['rabbitmq.list_users'](runas=runas)[name] - set(newtags)
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ def present(name,
|
||||||
name, runas=runas)
|
name, runas=runas)
|
||||||
changes['old'] += 'Removed password.\n'
|
changes['old'] += 'Removed password.\n'
|
||||||
|
|
||||||
if _check_tags_changes(name, tags):
|
if _check_tags_changes(name, tags, runas=runas):
|
||||||
if __opts__['test']:
|
if __opts__['test']:
|
||||||
ret['result'] = None
|
ret['result'] = None
|
||||||
ret['comment'] += ('Tags for user {0} '
|
ret['comment'] += ('Tags for user {0} '
|
||||||
|
@ -158,7 +158,7 @@ def present(name,
|
||||||
)
|
)
|
||||||
changes['new'] += 'Set tags: {0}\n'.format(tags)
|
changes['new'] += 'Set tags: {0}\n'.format(tags)
|
||||||
|
|
||||||
if _check_perms_changes(name, perms):
|
if _check_perms_changes(name, perms, runas=runas):
|
||||||
if __opts__['test']:
|
if __opts__['test']:
|
||||||
ret['result'] = None
|
ret['result'] = None
|
||||||
ret['comment'] += ('Permissions for user {0} '
|
ret['comment'] += ('Permissions for user {0} '
|
||||||
|
@ -167,7 +167,7 @@ def present(name,
|
||||||
for vhost_perm in perms:
|
for vhost_perm in perms:
|
||||||
for vhost, perm in six.iteritems(vhost_perm):
|
for vhost, perm in six.iteritems(vhost_perm):
|
||||||
result.update(__salt__['rabbitmq.set_permissions'](
|
result.update(__salt__['rabbitmq.set_permissions'](
|
||||||
vhost, name, perm[0], perm[1], perm[2], runas)
|
vhost, name, perm[0], perm[1], perm[2], runas=runas)
|
||||||
)
|
)
|
||||||
changes['new'] += (
|
changes['new'] += (
|
||||||
'Set permissions {0} for vhost {1}'
|
'Set permissions {0} for vhost {1}'
|
||||||
|
|
|
@ -1,11 +1,68 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
r'''
|
||||||
Manage the registry on Windows
|
===========================
|
||||||
|
Manage the Windows registry
|
||||||
|
===========================
|
||||||
|
Many python developers think of registry keys as if they were python keys in a
|
||||||
|
dictionary which is not the case. The windows registry is broken down into the
|
||||||
|
following components:
|
||||||
|
|
||||||
|
-----
|
||||||
|
Hives
|
||||||
|
-----
|
||||||
|
|
||||||
|
This is the top level of the registry. They all begin with HKEY.
|
||||||
|
- HKEY_CLASSES_ROOT (HKCR)
|
||||||
|
- HKEY_CURRENT_USER(HKCU)
|
||||||
|
- HKEY_LOCAL MACHINE (HKLM)
|
||||||
|
- HKEY_USER (HKU)
|
||||||
|
- HKEY_CURRENT_CONFIG
|
||||||
|
|
||||||
|
----
|
||||||
|
Keys
|
||||||
|
----
|
||||||
|
|
||||||
|
Hives contain keys. These are basically the folders beneath the hives. They can
|
||||||
|
contain any number of subkeys.
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
Values or Entries
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Values or Entries are the name/data pairs beneath the keys and subkeys. All keys
|
||||||
|
have a default name/data pair. It is usually "(Default)"="(value not set)". The
|
||||||
|
actual value for the name and the date is Null. The registry editor will display
|
||||||
|
"(Default)" and "(value not set)".
|
||||||
|
|
||||||
|
-------
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
The following example is taken from the windows startup portion of the registry:
|
||||||
|
```
|
||||||
|
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]
|
||||||
|
"RTHDVCPL"="\"C:\\Program Files\\Realtek\\Audio\\HDA\\RtkNGUI64.exe\" -s"
|
||||||
|
"NvBackend"="\"C:\\Program Files (x86)\\NVIDIA Corporation\\Update Core\\NvBackend.exe\""
|
||||||
|
"BTMTrayAgent"="rundll32.exe \"C:\\Program Files (x86)\\Intel\\Bluetooth\\btmshellex.dll\",TrayApp"
|
||||||
|
```
|
||||||
|
In this example these are the values for each:
|
||||||
|
|
||||||
|
Hive: `HKEY_LOCAL_MACHINE`
|
||||||
|
|
||||||
|
Key and subkeys: `SOFTWARE\Microsoft\Windows\CurrentVersion\Run`
|
||||||
|
|
||||||
|
Value:
|
||||||
|
- There are 3 value names: `RTHDVCPL`, `NvBackend`, and `BTMTrayAgent`
|
||||||
|
- Each value name has a corresponding value
|
||||||
'''
|
'''
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
# Import python libs
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
# Import salt libs
|
||||||
|
import salt.utils
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +80,7 @@ def _parse_key_value(key):
|
||||||
splt = key.split("\\")
|
splt = key.split("\\")
|
||||||
hive = splt.pop(0)
|
hive = splt.pop(0)
|
||||||
vname = splt.pop(-1)
|
vname = splt.pop(-1)
|
||||||
key = r'\\'.join(splt)
|
key = '\\'.join(splt)
|
||||||
return hive, key, vname
|
return hive, key, vname
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,71 +90,149 @@ def _parse_key(key):
|
||||||
'''
|
'''
|
||||||
splt = key.split("\\")
|
splt = key.split("\\")
|
||||||
hive = splt.pop(0)
|
hive = splt.pop(0)
|
||||||
key = r'\\'.join(splt)
|
key = '\\'.join(splt)
|
||||||
return hive, key
|
return hive, key
|
||||||
|
|
||||||
|
|
||||||
def present(name, value, vtype='REG_SZ', reflection=True):
|
def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection=True):
|
||||||
'''
|
'''
|
||||||
Set a registry value
|
Ensure a registry key or value is present.
|
||||||
|
|
||||||
Optionally set ``reflection`` to ``False`` to disable reflection.
|
:param str name:
|
||||||
``reflection`` has no effect on a 32-bit OS.
|
A string value representing the full path of the key to include the
|
||||||
|
HIVE, Key, and all Subkeys. For example:
|
||||||
|
|
||||||
In the example below, this will prevent Windows from silently creating
|
``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt``
|
||||||
the key in:
|
|
||||||
``HKEY_CURRENT_USER\\SOFTWARE\\Wow6432Node\\Salt\\version``
|
Valid hive values include:
|
||||||
|
- HKEY_CURRENT_USER or HKCU
|
||||||
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
|
- HKEY_USERS or HKU
|
||||||
|
|
||||||
|
:param str value:
|
||||||
|
Deprecated. Use vname and vdata instead. Included here for backwards
|
||||||
|
compatability.
|
||||||
|
|
||||||
|
:param str vname:
|
||||||
|
The name of the value you'd like to create beneath the Key. If this
|
||||||
|
parameter is not passed it will assume you want to set the (Default)
|
||||||
|
value
|
||||||
|
|
||||||
|
:param str vdata:
|
||||||
|
The value you'd like to set for the Key. If a value name (vname) is
|
||||||
|
passed, this will be the data for that value name. If not, this will be
|
||||||
|
the (Default) value for the key.
|
||||||
|
|
||||||
|
The type for the (Default) value is always REG_SZ and cannot be changed.
|
||||||
|
This parameter is optional. If not passed, the Key will be created with.
|
||||||
|
|
||||||
|
:param str vtype:
|
||||||
|
The value type for the data you wish to store in the registry. Valid
|
||||||
|
values are:
|
||||||
|
|
||||||
|
- REG_BINARY
|
||||||
|
- REG_DWORD
|
||||||
|
- REG_EXPAND_SZ
|
||||||
|
- REG_MULTI_SZ
|
||||||
|
- REG_SZ (Default)
|
||||||
|
|
||||||
|
:param bool reflection:
|
||||||
|
On 64 bit machines a duplicate value will be created in the
|
||||||
|
``Wow6432Node`` for 32bit programs. This only applies to the SOFTWARE
|
||||||
|
key. This option is ignored on 32bit operating systems. This value
|
||||||
|
defaults to True. Set it to False to disable reflection.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
Returns a dictionary showing the results of the registry operation.
|
||||||
|
:rtype: dict
|
||||||
|
|
||||||
|
The following example will set the ``(Default)`` value for the
|
||||||
|
``SOFTWARE\\Salt`` key in the ``HKEY_CURRENT_USER`` hive to ``0.15.3``. The
|
||||||
|
value will not be reflected in ``Wow6432Node``:
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
HKEY_CURRENT_USER\\SOFTWARE\\Salt\\version:
|
HKEY_CURRENT_USER\\SOFTWARE\\Salt:
|
||||||
reg.present:
|
reg.present:
|
||||||
- value: 0.15.3
|
- vdata: 0.15.3
|
||||||
- vtype: REG_SZ
|
|
||||||
- reflection: False
|
- reflection: False
|
||||||
|
|
||||||
|
The following example will set the value for the ``version`` entry under the
|
||||||
|
``SOFTWARE\\Salt`` key in the ``HKEY_CURRENT_USER`` hive to ``0.15.3``. The
|
||||||
|
value will be reflected in ``Wow6432Node``:
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
HKEY_CURRENT_USER\\SOFTWARE\\Salt:
|
||||||
|
reg.present:
|
||||||
|
- vname: version
|
||||||
|
- vdata: 0.15.3
|
||||||
|
|
||||||
In the above example the path is interpreted as follows:
|
In the above example the path is interpreted as follows:
|
||||||
- ``HKEY_CURRENT_USER`` is the hive
|
- ``HKEY_CURRENT_USER`` is the hive
|
||||||
- ``SOFTWARE\\Salt`` is the key
|
- ``SOFTWARE\\Salt`` is the key
|
||||||
- ``version`` is the value name
|
- ``vname`` is the value name ('version') that will be created under the key
|
||||||
So ``version`` will be created in the ``SOFTWARE\\Salt`` key in the
|
- ``vdata`` is the data that will be assigned to 'version'
|
||||||
``HKEY_CURRENT_USER`` hive and given the ``REG_SZ`` value of ``0.15.3``.
|
|
||||||
'''
|
'''
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'result': True,
|
'result': True,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
'comment': ''}
|
'comment': ''}
|
||||||
|
|
||||||
hive, key, vname = _parse_key_value(name)
|
# This is for backwards compatibility
|
||||||
|
# If 'value' is passed a value, vdata becomes value and the vname is
|
||||||
|
# obtained from the key path
|
||||||
|
if value:
|
||||||
|
hive, key, vname = _parse_key_value(name)
|
||||||
|
vdata = value
|
||||||
|
ret['comment'] = 'State file is using deprecated syntax. Please update.'
|
||||||
|
salt.utils.warn_until(
|
||||||
|
'Boron',
|
||||||
|
'The \'value\' argument has been deprecated. '
|
||||||
|
'Please use vdata instead.'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
hive, key = _parse_key(name)
|
||||||
|
|
||||||
# Determine what to do
|
# Determine what to do
|
||||||
if value == __salt__['reg.read_value'](hive, key, vname)['vdata']:
|
reg_current = __salt__['reg.read_value'](hive, key, vname)
|
||||||
ret['comment'] = '{0} is already configured'.format(name)
|
|
||||||
|
if vdata == reg_current['vdata'] and reg_current['success']:
|
||||||
|
ret['comment'] = '{0} in {1} is already configured'.\
|
||||||
|
format(vname if vname else '(Default)', name)
|
||||||
return ret
|
return ret
|
||||||
else:
|
|
||||||
ret['changes'] = {'reg': 'configured to {0}'.format(value)}
|
add_change = {'Key': r'{0}\{1}'.format(hive, key),
|
||||||
|
'Entry': '{0}'.format(vname if vname else '(Default)'),
|
||||||
|
'Value': '{0}'.format(vdata if vdata else '(Empty String)')}
|
||||||
|
|
||||||
# Check for test option
|
# Check for test option
|
||||||
if __opts__['test']:
|
if __opts__['test']:
|
||||||
ret['result'] = None
|
ret['result'] = None
|
||||||
|
ret['changes'] = {'reg': {'Will add': add_change}}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# Configure the value
|
# Configure the value
|
||||||
ret['result'] = __salt__['reg.set_value'](hive, key, vname, value, vtype,
|
ret['result'] = __salt__['reg.set_value'](hive, key, vname, vdata, vtype,
|
||||||
reflection)
|
reflection)
|
||||||
|
|
||||||
if not ret:
|
if not ret['result']:
|
||||||
ret['changes'] = {}
|
ret['changes'] = {}
|
||||||
ret['comment'] = 'could not configure the registry key'
|
ret['comment'] = r'Failed to add {0} to {1}\{2}'.format(name, hive, key)
|
||||||
|
else:
|
||||||
|
ret['changes'] = {'reg': {'Added': add_change}}
|
||||||
|
ret['comment'] = r'Added {0} to {1}\{2}'.format(name, hive, key)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def absent(name):
|
def absent(name, vname=None):
|
||||||
'''
|
'''
|
||||||
Remove a registry value
|
Ensure a registry value is removed. To remove a key use key_absent.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -118,14 +253,89 @@ def absent(name):
|
||||||
'changes': {},
|
'changes': {},
|
||||||
'comment': ''}
|
'comment': ''}
|
||||||
|
|
||||||
hive, key, vname = _parse_key_value(name)
|
hive, key = _parse_key(name)
|
||||||
|
|
||||||
# Determine what to do
|
# Determine what to do
|
||||||
if not __salt__['reg.read_value'](hive, key, vname)['success']:
|
if not __salt__['reg.read_value'](hive, key, vname)['success']:
|
||||||
|
hive, key, vname = _parse_key_value(name)
|
||||||
|
if not __salt__['reg.read_value'](hive, key, vname)['success']:
|
||||||
|
ret['comment'] = '{0} is already absent'.format(name)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
remove_change = {'Key': r'{0}\{1}'.format(hive, key),
|
||||||
|
'Entry': '{0}'.format(vname if vname else '(Default)')}
|
||||||
|
|
||||||
|
# Check for test option
|
||||||
|
if __opts__['test']:
|
||||||
|
ret['result'] = None
|
||||||
|
ret['changes'] = {'reg': {'Will remove': remove_change}}
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# Delete the value
|
||||||
|
ret['result'] = __salt__['reg.delete_value'](hive, key, vname)
|
||||||
|
if not ret['result']:
|
||||||
|
ret['changes'] = {}
|
||||||
|
ret['comment'] = r'Failed to remove {0} from {1}\{2}'.format(name, hive,
|
||||||
|
key)
|
||||||
|
else:
|
||||||
|
ret['changes'] = {'reg': {'Removed': remove_change}}
|
||||||
|
ret['comment'] = r'Removed {0} from {1}\{2}'.format(name, hive, key)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def key_absent(name, force=False):
|
||||||
|
r'''
|
||||||
|
.. versionadded:: 2015.5.4
|
||||||
|
|
||||||
|
Ensure a registry key is removed. This will remove a key and all value
|
||||||
|
entries it contains. It will fail if the key contains subkeys.
|
||||||
|
|
||||||
|
:param str name:
|
||||||
|
A string representing the full path to the key to be removed to include
|
||||||
|
the hive and the keypath. The hive can be any of the following:
|
||||||
|
- HKEY_LOCAL_MACHINE or HKLM
|
||||||
|
- HKEY_CURRENT_USER or HKCU
|
||||||
|
- HKEY_USER or HKU
|
||||||
|
|
||||||
|
:param bool force:
|
||||||
|
A boolean value indicating that all subkeys should be deleted with the
|
||||||
|
key. If force=False and subkeys exists beneath the key you want to
|
||||||
|
delete, key_absent will fail. Use with caution. The default is False.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
Returns a dictionary showing the results of the registry operation.
|
||||||
|
:rtype: dict
|
||||||
|
|
||||||
|
The following example will delete the ``SOFTWARE\Salt`` key and all subkeys
|
||||||
|
under the ``HKEY_CURRENT_USER`` hive.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
'HKEY_CURRENT_USER\SOFTWARE\Salt':
|
||||||
|
reg.key_absent:
|
||||||
|
- force: True
|
||||||
|
|
||||||
|
In the above example the path is interpreted as follows:
|
||||||
|
- ``HKEY_CURRENT_USER`` is the hive
|
||||||
|
- ``SOFTWARE\Salt`` is the key
|
||||||
|
'''
|
||||||
|
ret = {'name': name,
|
||||||
|
'result': True,
|
||||||
|
'changes': {},
|
||||||
|
'comment': ''}
|
||||||
|
|
||||||
|
hive, key = _parse_key(name)
|
||||||
|
|
||||||
|
# Determine what to do
|
||||||
|
if not __salt__['reg.read_value'](hive, key)['success']:
|
||||||
ret['comment'] = '{0} is already absent'.format(name)
|
ret['comment'] = '{0} is already absent'.format(name)
|
||||||
return ret
|
return ret
|
||||||
else:
|
|
||||||
ret['changes'] = {'reg': 'Removed {0}'.format(name)}
|
ret['changes'] = {'reg': {
|
||||||
|
'Removed': {
|
||||||
|
'Key': r'{0}\{1}'.format(hive, key)
|
||||||
|
}}}
|
||||||
|
|
||||||
# Check for test option
|
# Check for test option
|
||||||
if __opts__['test']:
|
if __opts__['test']:
|
||||||
|
@ -133,9 +343,10 @@ def absent(name):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# Delete the value
|
# Delete the value
|
||||||
ret['result'] = __salt__['reg.delete_value'](hive, key, vname)
|
__salt__['reg.delete_key'](hive, key, force=force)
|
||||||
if not ret['result']:
|
if __salt__['reg.read_value'](hive, key)['success']:
|
||||||
|
ret['result'] = False
|
||||||
ret['changes'] = {}
|
ret['changes'] = {}
|
||||||
ret['comment'] = 'failed to remove registry key {0}'.format(name)
|
ret['comment'] = 'Failed to remove registry key {0}'.format(name)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
'''
|
||||||
Manage Windows Package Repository
|
Manage Windows Package Repository
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This state only loads on minions that have the ``roles: salt-master`` grain
|
|
||||||
set.
|
|
||||||
'''
|
'''
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
@ -21,15 +16,7 @@ import salt.config
|
||||||
|
|
||||||
|
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
'''
|
return 'winrepo'
|
||||||
Load this state if this is the salt-master
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
return ('winrepo'
|
|
||||||
if 'salt-master' in __grains__.get('roles', [])
|
|
||||||
else False)
|
|
||||||
except TypeError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def genrepo(name, force=False, allow_empty=False):
|
def genrepo(name, force=False, allow_empty=False):
|
||||||
|
|
|
@ -68,7 +68,7 @@ def get_iam_region(version='latest', url='http://169.254.169.254',
|
||||||
'''
|
'''
|
||||||
Gets instance identity document and returns region
|
Gets instance identity document and returns region
|
||||||
'''
|
'''
|
||||||
instance_identity_url = '{0}/{1}/latest/dynamic/instance-identity/document'.format(url, version)
|
instance_identity_url = '{0}/{1}/dynamic/instance-identity/document'.format(url, version)
|
||||||
|
|
||||||
region = None
|
region = None
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -273,7 +273,7 @@ class SerializerExtension(Extension, object):
|
||||||
{%- set json_src = "{'bar': 'for real'}"|load_json %}
|
{%- set json_src = "{'bar': 'for real'}"|load_json %}
|
||||||
Dude, {{ yaml_src.foo }} {{ json_src.bar }}!
|
Dude, {{ yaml_src.foo }} {{ json_src.bar }}!
|
||||||
|
|
||||||
will be rendered has::
|
will be rendered as::
|
||||||
|
|
||||||
Dude, it works for real!
|
Dude, it works for real!
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ class SerializerExtension(Extension, object):
|
||||||
{% endload %}
|
{% endload %}
|
||||||
Dude, {{ yaml_src.foo }} {{ json_src.bar }}!
|
Dude, {{ yaml_src.foo }} {{ json_src.bar }}!
|
||||||
|
|
||||||
will be rendered has::
|
will be rendered as::
|
||||||
|
|
||||||
Dude, it works for real!
|
Dude, it works for real!
|
||||||
|
|
||||||
|
|
327
setup.py
327
setup.py
|
@ -5,7 +5,7 @@ The setup script for salt
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
# pylint: disable=file-perms
|
||||||
# pylint: disable=C0111,E1101,E1103,F0401,W0611,W0201,W0232,R0201,R0902,R0903
|
# pylint: disable=C0111,E1101,E1103,F0401,W0611,W0201,W0232,R0201,R0902,R0903
|
||||||
|
|
||||||
# For Python 2.5. A no-op on 2.6 and above.
|
# For Python 2.5. A no-op on 2.6 and above.
|
||||||
|
@ -18,7 +18,7 @@ import time
|
||||||
try:
|
try:
|
||||||
from urllib2 import urlopen
|
from urllib2 import urlopen
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen # pylint: disable=no-name-in-module
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
# pylint: disable=E0611
|
# pylint: disable=E0611
|
||||||
import distutils.dist
|
import distutils.dist
|
||||||
|
@ -71,6 +71,7 @@ WITH_SETUPTOOLS = False
|
||||||
if 'USE_SETUPTOOLS' in os.environ or 'setuptools' in sys.modules:
|
if 'USE_SETUPTOOLS' in os.environ or 'setuptools' in sys.modules:
|
||||||
try:
|
try:
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
from setuptools.command.develop import develop
|
||||||
from setuptools.command.install import install
|
from setuptools.command.install import install
|
||||||
from setuptools.command.sdist import sdist
|
from setuptools.command.sdist import sdist
|
||||||
from setuptools.command.egg_info import egg_info
|
from setuptools.command.egg_info import egg_info
|
||||||
|
@ -103,6 +104,7 @@ except ImportError:
|
||||||
|
|
||||||
SALT_VERSION = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', 'version.py')
|
SALT_VERSION = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', 'version.py')
|
||||||
SALT_VERSION_HARDCODED = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', '_version.py')
|
SALT_VERSION_HARDCODED = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', '_version.py')
|
||||||
|
SALT_SYSPATHS_HARDCODED = os.path.join(os.path.abspath(SETUP_DIRNAME), 'salt', '_syspaths.py')
|
||||||
SALT_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'base.txt')
|
SALT_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'base.txt')
|
||||||
SALT_ZEROMQ_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'zeromq.txt')
|
SALT_ZEROMQ_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'zeromq.txt')
|
||||||
SALT_RAET_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'raet.txt')
|
SALT_RAET_REQS = os.path.join(os.path.abspath(SETUP_DIRNAME), 'requirements', 'raet.txt')
|
||||||
|
@ -125,8 +127,16 @@ def _parse_requirements_file(requirements_file):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line or line.startswith(('#', '-r')):
|
if not line or line.startswith(('#', '-r')):
|
||||||
continue
|
continue
|
||||||
if IS_WINDOWS_PLATFORM and 'libcloud' in line:
|
if IS_WINDOWS_PLATFORM:
|
||||||
continue
|
if 'libcloud' in line:
|
||||||
|
continue
|
||||||
|
if 'pycrypto' in line.lower():
|
||||||
|
# On windows we install PyCrypto using python wheels
|
||||||
|
continue
|
||||||
|
if 'm2crypto' in line.lower() and __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
||||||
|
# In Windows, we're installing M2CryptoWin{32,64} which comes
|
||||||
|
# compiled
|
||||||
|
continue
|
||||||
parsed_requirements.append(line)
|
parsed_requirements.append(line)
|
||||||
return parsed_requirements
|
return parsed_requirements
|
||||||
# <---- Helper Functions ---------------------------------------------------------------------------------------------
|
# <---- Helper Functions ---------------------------------------------------------------------------------------------
|
||||||
|
@ -139,10 +149,14 @@ class WriteSaltVersion(Command):
|
||||||
user_options = []
|
user_options = []
|
||||||
|
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
pass
|
'''
|
||||||
|
Abstract method that is required to be overwritten
|
||||||
|
'''
|
||||||
|
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
pass
|
'''
|
||||||
|
Abstract method that is required to be overwritten
|
||||||
|
'''
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not os.path.exists(SALT_VERSION_HARDCODED):
|
if not os.path.exists(SALT_VERSION_HARDCODED):
|
||||||
|
@ -161,10 +175,9 @@ class WriteSaltVersion(Command):
|
||||||
# pylint: enable=E0602
|
# pylint: enable=E0602
|
||||||
|
|
||||||
|
|
||||||
class WriteSaltSshPackaingFile(Command):
|
class GenerateSaltSyspaths(Command):
|
||||||
|
|
||||||
description = 'Write salt\'s ssh packaging file'
|
description = 'Generate salt\'s hardcoded syspaths file'
|
||||||
user_options = []
|
|
||||||
|
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
pass
|
pass
|
||||||
|
@ -172,6 +185,45 @@ class WriteSaltSshPackaingFile(Command):
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# Write the syspaths file
|
||||||
|
if getattr(self.distribution, 'salt_syspaths_hardcoded_path', None) is None:
|
||||||
|
print('This command is not meant to be called on it\'s own')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Write the system paths file
|
||||||
|
open(self.distribution.salt_syspaths_hardcoded_path, 'w').write(
|
||||||
|
INSTALL_SYSPATHS_TEMPLATE.format(
|
||||||
|
date=datetime.utcnow(),
|
||||||
|
root_dir=self.distribution.salt_root_dir,
|
||||||
|
config_dir=self.distribution.salt_config_dir,
|
||||||
|
cache_dir=self.distribution.salt_cache_dir,
|
||||||
|
sock_dir=self.distribution.salt_sock_dir,
|
||||||
|
srv_root_dir=self.distribution.salt_srv_root_dir,
|
||||||
|
base_file_roots_dir=self.distribution.salt_base_file_roots_dir,
|
||||||
|
base_pillar_roots_dir=self.distribution.salt_base_pillar_roots_dir,
|
||||||
|
base_master_roots_dir=self.distribution.salt_base_master_roots_dir,
|
||||||
|
logs_dir=self.distribution.salt_logs_dir,
|
||||||
|
pidfile_dir=self.distribution.salt_pidfile_dir,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WriteSaltSshPackaingFile(Command):
|
||||||
|
|
||||||
|
description = 'Write salt\'s ssh packaging file'
|
||||||
|
user_options = []
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
'''
|
||||||
|
Abstract method that is required to be overwritten
|
||||||
|
'''
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
'''
|
||||||
|
Abstract method that is required to be overwritten
|
||||||
|
'''
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not os.path.exists(PACKAGED_FOR_SALT_SSH_FILE):
|
if not os.path.exists(PACKAGED_FOR_SALT_SSH_FILE):
|
||||||
# Write the salt-ssh packaging file
|
# Write the salt-ssh packaging file
|
||||||
|
@ -184,6 +236,198 @@ class WriteSaltSshPackaingFile(Command):
|
||||||
# pylint: enable=E0602
|
# pylint: enable=E0602
|
||||||
|
|
||||||
|
|
||||||
|
if WITH_SETUPTOOLS:
|
||||||
|
class Develop(develop):
|
||||||
|
user_options = develop.user_options + [
|
||||||
|
('write_salt_version', None,
|
||||||
|
'Generate Salt\'s _version.py file which allows proper version '
|
||||||
|
'reporting. This defaults to False on develop/editable setups. '
|
||||||
|
'If WRITE_SALT_VERSION is found in the environment this flag is '
|
||||||
|
'switched to True.'),
|
||||||
|
('generate_salt_syspaths', None,
|
||||||
|
'Generate Salt\'s _syspaths.py file which allows tweaking some '
|
||||||
|
'common paths that salt uses. This defaults to False on '
|
||||||
|
'develop/editable setups. If GENERATE_SALT_SYSPATHS is found in '
|
||||||
|
'the environment this flag is switched to True.'),
|
||||||
|
('mimic_salt_install', None,
|
||||||
|
'Mimmic the install command when running the develop command. '
|
||||||
|
'This will generate salt\'s _version.py and _syspaths.py files. '
|
||||||
|
'Generate Salt\'s _syspaths.py file which allows tweaking some '
|
||||||
|
'This defaults to False on develop/editable setups. '
|
||||||
|
'If MIMIC_INSTALL is found in the environment this flag is '
|
||||||
|
'switched to True.')
|
||||||
|
]
|
||||||
|
boolean_options = develop.boolean_options + [
|
||||||
|
'write_salt_version',
|
||||||
|
'generate_salt_syspaths',
|
||||||
|
'mimic_salt_install'
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
develop.initialize_options(self)
|
||||||
|
self.write_salt_version = False
|
||||||
|
self.generate_salt_syspaths = False
|
||||||
|
self.mimic_salt_install = False
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
develop.finalize_options(self)
|
||||||
|
if 'WRITE_SALT_VERSION' in os.environ:
|
||||||
|
self.write_salt_version = True
|
||||||
|
if 'GENERATE_SALT_SYSPATHS' in os.environ:
|
||||||
|
self.generate_salt_syspaths = True
|
||||||
|
if 'MIMIC_SALT_INSTALL' in os.environ:
|
||||||
|
self.mimic_salt_install = True
|
||||||
|
|
||||||
|
if self.mimic_salt_install:
|
||||||
|
self.write_salt_version = True
|
||||||
|
self.generate_salt_syspaths = True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if IS_WINDOWS_PLATFORM:
|
||||||
|
if __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
||||||
|
# Install M2Crypto first
|
||||||
|
self.distribution.salt_installing_m2crypto_windows = True
|
||||||
|
self.run_command('install-m2crypto-windows')
|
||||||
|
self.distribution.salt_installing_m2crypto_windows = None
|
||||||
|
|
||||||
|
# Install PyCrypto
|
||||||
|
self.distribution.salt_installing_pycrypto_windows = True
|
||||||
|
self.run_command('install-pycrypto-windows')
|
||||||
|
self.distribution.salt_installing_pycrypto_windows = None
|
||||||
|
|
||||||
|
# Download the required DLLs
|
||||||
|
self.distribution.salt_download_windows_dlls = True
|
||||||
|
self.run_command('download-windows-dlls')
|
||||||
|
self.distribution.salt_download_windows_dlls = None
|
||||||
|
|
||||||
|
if self.write_salt_version is True:
|
||||||
|
self.distribution.running_salt_install = True
|
||||||
|
self.distribution.salt_version_hardcoded_path = SALT_VERSION_HARDCODED
|
||||||
|
self.run_command('write_salt_version')
|
||||||
|
|
||||||
|
if self.generate_salt_syspaths:
|
||||||
|
self.distribution.salt_syspaths_hardcoded_path = SALT_SYSPATHS_HARDCODED
|
||||||
|
self.run_command('generate_salt_syspaths')
|
||||||
|
|
||||||
|
# Resume normal execution
|
||||||
|
develop.run(self)
|
||||||
|
|
||||||
|
|
||||||
|
class InstallM2CryptoWindows(Command):
|
||||||
|
|
||||||
|
description = 'Install M2CryptoWindows'
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if getattr(self.distribution, 'salt_installing_m2crypto_windows', None) is None:
|
||||||
|
print('This command is not meant to be called on it\'s own')
|
||||||
|
exit(1)
|
||||||
|
import platform
|
||||||
|
from pip.utils import call_subprocess
|
||||||
|
from pip.utils.logging import indent_log
|
||||||
|
platform_bits, _ = platform.architecture()
|
||||||
|
with indent_log():
|
||||||
|
call_subprocess(
|
||||||
|
['pip', 'install', '--egg', 'M2CryptoWin{0}'.format(platform_bits[:2])]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InstallPyCryptoWindowsWheel(Command):
|
||||||
|
|
||||||
|
description = 'Install PyCrypto on Windows'
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if getattr(self.distribution, 'salt_installing_pycrypto_windows', None) is None:
|
||||||
|
print('This command is not meant to be called on it\'s own')
|
||||||
|
exit(1)
|
||||||
|
import platform
|
||||||
|
from pip.utils import call_subprocess
|
||||||
|
from pip.utils.logging import indent_log
|
||||||
|
platform_bits, _ = platform.architecture()
|
||||||
|
call_arguments = ['pip', 'install', 'wheel']
|
||||||
|
if platform_bits == '64bit':
|
||||||
|
call_arguments.append(
|
||||||
|
'http://repo.saltstack.com/windows/dependencies/64/pycrypto-2.6.1-cp27-none-win_amd64.whl'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
call_arguments.append(
|
||||||
|
'http://repo.saltstack.com/windows/dependencies/32/pycrypto-2.6.1-cp27-none-win32.whl'
|
||||||
|
)
|
||||||
|
with indent_log():
|
||||||
|
call_subprocess(call_arguments)
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadWindowsDlls(Command):
|
||||||
|
|
||||||
|
description = 'Download required DLL\'s for windows'
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def finalize_options(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if getattr(self.distribution, 'salt_download_windows_dlls', None) is None:
|
||||||
|
print('This command is not meant to be called on it\'s own')
|
||||||
|
exit(1)
|
||||||
|
import platform
|
||||||
|
from pip.utils.logging import indent_log
|
||||||
|
platform_bits, _ = platform.architecture()
|
||||||
|
url = 'https://repo.saltstack.com/windows/dependencies/{bits}/{fname}32.dll'
|
||||||
|
dest = os.path.join(os.path.dirname(sys.executable), '{fname}32.dll')
|
||||||
|
with indent_log():
|
||||||
|
for fname in ('libeay', 'ssleay'):
|
||||||
|
furl = url.format(bits=platform_bits[:2], fname=fname)
|
||||||
|
fdest = dest.format(fname=fname)
|
||||||
|
if not os.path.exists(fdest):
|
||||||
|
log.info('Downloading {0}32.dll to {1} from {2}'.format(fname, fdest, furl))
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
from contextlib import closing
|
||||||
|
with closing(requests.get(furl, stream=True)) as req:
|
||||||
|
if req.status_code == 200:
|
||||||
|
with open(fdest, 'w') as wfh:
|
||||||
|
for chunk in req.iter_content(chunk_size=4096):
|
||||||
|
if chunk: # filter out keep-alive new chunks
|
||||||
|
wfh.write(chunk)
|
||||||
|
wfh.flush()
|
||||||
|
else:
|
||||||
|
log.error(
|
||||||
|
'Failed to download {0}32.dll to {1} from {2}'.format(
|
||||||
|
fname, fdest, furl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
req = urlopen(furl)
|
||||||
|
|
||||||
|
if req.getcode() == 200:
|
||||||
|
with open(fdest, 'w') as wfh:
|
||||||
|
while True:
|
||||||
|
for chunk in req.read(4096):
|
||||||
|
if not chunk:
|
||||||
|
break
|
||||||
|
wfh.write(chunk)
|
||||||
|
wfh.flush()
|
||||||
|
else:
|
||||||
|
log.error(
|
||||||
|
'Failed to download {0}32.dll to {1} from {2}'.format(
|
||||||
|
fname, fdest, furl
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Sdist(sdist):
|
class Sdist(sdist):
|
||||||
|
|
||||||
def make_release_tree(self, base_dir, files):
|
def make_release_tree(self, base_dir, files):
|
||||||
|
@ -318,7 +562,9 @@ class TestCommand(Command):
|
||||||
self.runtests_opts = None
|
self.runtests_opts = None
|
||||||
|
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
pass
|
'''
|
||||||
|
Abstract method that is required to be overwritten
|
||||||
|
'''
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
@ -389,24 +635,10 @@ class Build(build):
|
||||||
self.run_command('write_salt_version')
|
self.run_command('write_salt_version')
|
||||||
|
|
||||||
# Write the system paths file
|
# Write the system paths file
|
||||||
system_paths_file_path = os.path.join(
|
self.distribution.salt_syspaths_hardcoded_path = os.path.join(
|
||||||
self.build_lib, 'salt', '_syspaths.py'
|
self.build_lib, 'salt', '_syspaths.py'
|
||||||
)
|
)
|
||||||
open(system_paths_file_path, 'w').write(
|
self.run_command('generate_salt_syspaths')
|
||||||
INSTALL_SYSPATHS_TEMPLATE.format(
|
|
||||||
date=datetime.utcnow(),
|
|
||||||
root_dir=self.distribution.salt_root_dir,
|
|
||||||
config_dir=self.distribution.salt_config_dir,
|
|
||||||
cache_dir=self.distribution.salt_cache_dir,
|
|
||||||
sock_dir=self.distribution.salt_sock_dir,
|
|
||||||
srv_root_dir=self.distribution.salt_srv_root_dir,
|
|
||||||
base_file_roots_dir=self.distribution.salt_base_file_roots_dir,
|
|
||||||
base_pillar_roots_dir=self.distribution.salt_base_pillar_roots_dir,
|
|
||||||
base_master_roots_dir=self.distribution.salt_base_master_roots_dir,
|
|
||||||
logs_dir=self.distribution.salt_logs_dir,
|
|
||||||
pidfile_dir=self.distribution.salt_pidfile_dir,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Install(install):
|
class Install(install):
|
||||||
|
@ -499,6 +731,20 @@ class Install(install):
|
||||||
self.distribution.salt_version_hardcoded_path = os.path.join(
|
self.distribution.salt_version_hardcoded_path = os.path.join(
|
||||||
self.build_lib, 'salt', '_version.py'
|
self.build_lib, 'salt', '_version.py'
|
||||||
)
|
)
|
||||||
|
if IS_WINDOWS_PLATFORM:
|
||||||
|
if __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
||||||
|
# Install M2Crypto first
|
||||||
|
self.distribution.salt_installing_m2crypto_windows = True
|
||||||
|
self.run_command('install-m2crypto-windows')
|
||||||
|
self.distribution.salt_installing_m2crypto_windows = None
|
||||||
|
# Install PyCrypto
|
||||||
|
self.distribution.salt_installing_pycrypto_windows = True
|
||||||
|
self.run_command('install-pycrypto-windows')
|
||||||
|
self.distribution.salt_installing_pycrypto_windows = None
|
||||||
|
# Download the required DLLs
|
||||||
|
self.distribution.salt_download_windows_dlls = True
|
||||||
|
self.run_command('download-windows-dlls')
|
||||||
|
self.distribution.salt_download_windows_dlls = None
|
||||||
# Run install.run
|
# Run install.run
|
||||||
install.run(self)
|
install.run(self)
|
||||||
|
|
||||||
|
@ -597,7 +843,6 @@ class SaltDistribution(distutils.dist.Distribution):
|
||||||
self.salt_logs_dir = None
|
self.salt_logs_dir = None
|
||||||
self.salt_pidfile_dir = None
|
self.salt_pidfile_dir = None
|
||||||
|
|
||||||
|
|
||||||
self.name = 'salt-ssh' if PACKAGED_FOR_SALT_SSH else 'salt'
|
self.name = 'salt-ssh' if PACKAGED_FOR_SALT_SSH else 'salt'
|
||||||
self.salt_version = __version__ # pylint: disable=undefined-variable
|
self.salt_version = __version__ # pylint: disable=undefined-variable
|
||||||
self.description = 'Portable, distributed, remote execution and configuration management system'
|
self.description = 'Portable, distributed, remote execution and configuration management system'
|
||||||
|
@ -610,10 +855,19 @@ class SaltDistribution(distutils.dist.Distribution):
|
||||||
'sdist': Sdist,
|
'sdist': Sdist,
|
||||||
'install': Install,
|
'install': Install,
|
||||||
'write_salt_version': WriteSaltVersion,
|
'write_salt_version': WriteSaltVersion,
|
||||||
|
'generate_salt_syspaths': GenerateSaltSyspaths,
|
||||||
'write_salt_ssh_packaging_file': WriteSaltSshPackaingFile})
|
'write_salt_ssh_packaging_file': WriteSaltSshPackaingFile})
|
||||||
if not IS_WINDOWS_PLATFORM:
|
if not IS_WINDOWS_PLATFORM:
|
||||||
self.cmdclass.update({'sdist': CloudSdist,
|
self.cmdclass.update({'sdist': CloudSdist,
|
||||||
'install_lib': InstallLib})
|
'install_lib': InstallLib})
|
||||||
|
if IS_WINDOWS_PLATFORM:
|
||||||
|
self.cmdclass.update({'install-pycrypto-windows': InstallPyCryptoWindowsWheel,
|
||||||
|
'download-windows-dlls': DownloadWindowsDlls})
|
||||||
|
if __saltstack_version__.info < (2015, 8): # pylint: disable=undefined-variable
|
||||||
|
self.cmdclass.update({'install-m2crypto-windows': InstallM2CryptoWindows})
|
||||||
|
|
||||||
|
if WITH_SETUPTOOLS:
|
||||||
|
self.cmdclass.update({'develop': Develop})
|
||||||
|
|
||||||
self.license = 'Apache Software License 2.0'
|
self.license = 'Apache Software License 2.0'
|
||||||
self.packages = self.discover_packages()
|
self.packages = self.discover_packages()
|
||||||
|
@ -731,6 +985,7 @@ class SaltDistribution(distutils.dist.Distribution):
|
||||||
|
|
||||||
if IS_WINDOWS_PLATFORM:
|
if IS_WINDOWS_PLATFORM:
|
||||||
install_requires.append('WMI')
|
install_requires.append('WMI')
|
||||||
|
install_requires.append('pypiwin32 >= 219')
|
||||||
|
|
||||||
if self.salt_transport == 'zeromq':
|
if self.salt_transport == 'zeromq':
|
||||||
install_requires += _parse_requirements_file(SALT_ZEROMQ_REQS)
|
install_requires += _parse_requirements_file(SALT_ZEROMQ_REQS)
|
||||||
|
@ -911,14 +1166,6 @@ class SaltDistribution(distutils.dist.Distribution):
|
||||||
def parse_command_line(self):
|
def parse_command_line(self):
|
||||||
args = distutils.dist.Distribution.parse_command_line(self)
|
args = distutils.dist.Distribution.parse_command_line(self)
|
||||||
|
|
||||||
# Setup our property functions after class initialization and
|
|
||||||
# after parsing the command line since most are set to None
|
|
||||||
for funcname in dir(self):
|
|
||||||
if not funcname.startswith('_property_'):
|
|
||||||
continue
|
|
||||||
property_name = funcname.split('_property_', 1)[-1]
|
|
||||||
setattr(self, property_name, getattr(self, funcname))
|
|
||||||
|
|
||||||
if not self.ssh_packaging and PACKAGED_FOR_SALT_SSH:
|
if not self.ssh_packaging and PACKAGED_FOR_SALT_SSH:
|
||||||
self.ssh_packaging = 1
|
self.ssh_packaging = 1
|
||||||
|
|
||||||
|
@ -936,6 +1183,16 @@ class SaltDistribution(distutils.dist.Distribution):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Setup our property functions after class initialization and
|
||||||
|
# after parsing the command line since most are set to None
|
||||||
|
# ATTENTION: This should be the last step before returning the args or
|
||||||
|
# some of the requirements won't be correctly set
|
||||||
|
for funcname in dir(self):
|
||||||
|
if not funcname.startswith('_property_'):
|
||||||
|
continue
|
||||||
|
property_name = funcname.split('_property_', 1)[-1]
|
||||||
|
setattr(self, property_name, getattr(self, funcname))
|
||||||
|
|
||||||
return args
|
return args
|
||||||
# <---- Overridden Methods ---------------------------------------------------------------------------------------
|
# <---- Overridden Methods ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,11 @@ from salttesting.mock import (
|
||||||
# Import Salt Libs
|
# Import Salt Libs
|
||||||
from salt.modules import pw_user
|
from salt.modules import pw_user
|
||||||
from salt.exceptions import CommandExecutionError
|
from salt.exceptions import CommandExecutionError
|
||||||
import pwd
|
try:
|
||||||
|
import pwd
|
||||||
|
HAS_PWD = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_PWD = False
|
||||||
|
|
||||||
|
|
||||||
# Globals
|
# Globals
|
||||||
|
@ -27,6 +31,7 @@ pw_user.__salt__ = {}
|
||||||
pw_user.__context__ = {}
|
pw_user.__context__ = {}
|
||||||
|
|
||||||
|
|
||||||
|
@skipIf(not HAS_PWD, 'These tests can only run on systems with the python pwd module')
|
||||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
class PwUserTestCase(TestCase):
|
class PwUserTestCase(TestCase):
|
||||||
'''
|
'''
|
||||||
|
@ -49,16 +54,21 @@ class PwUserTestCase(TestCase):
|
||||||
with patch.dict(pw_user.__salt__, {'cmd.run_all': mock}):
|
with patch.dict(pw_user.__salt__, {'cmd.run_all': mock}):
|
||||||
self.assertTrue(pw_user.delete('A'), 1)
|
self.assertTrue(pw_user.delete('A'), 1)
|
||||||
|
|
||||||
@patch('salt.modules.pw_user.__context__', MagicMock(return_value='A'))
|
|
||||||
def test_getent(self):
|
def test_getent(self):
|
||||||
'''
|
'''
|
||||||
Test if user.getent already have a value
|
Test if user.getent already have a value
|
||||||
'''
|
'''
|
||||||
self.assertTrue(pw_user.getent())
|
mock_user = 'saltdude'
|
||||||
|
|
||||||
mock = MagicMock(return_value='A')
|
class MockData(object):
|
||||||
with patch.object(pw_user, 'info', mock):
|
pw_name = mock_user
|
||||||
self.assertEqual(pw_user.getent(True)[0], 'A')
|
|
||||||
|
with patch('pwd.getpwall', MagicMock(return_value=[MockData()])):
|
||||||
|
with patch.dict(pw_user.__context__, {'user.getent': mock_user}):
|
||||||
|
self.assertEqual(pw_user.getent(), mock_user)
|
||||||
|
|
||||||
|
with patch.object(pw_user, 'info', MagicMock(return_value=mock_user)):
|
||||||
|
self.assertEqual(pw_user.getent(True)[0], mock_user)
|
||||||
|
|
||||||
def test_chuid(self):
|
def test_chuid(self):
|
||||||
'''
|
'''
|
||||||
|
@ -291,13 +301,22 @@ class PwUserTestCase(TestCase):
|
||||||
'''
|
'''
|
||||||
Return a list of groups the named user belongs to
|
Return a list of groups the named user belongs to
|
||||||
'''
|
'''
|
||||||
self.assertEqual(pw_user.list_groups('name'), 'A')
|
mock_group = 'saltgroup'
|
||||||
|
|
||||||
|
with patch('salt.utils.get_group_list', MagicMock(return_value=[mock_group])):
|
||||||
|
self.assertEqual(pw_user.list_groups('name'), [mock_group])
|
||||||
|
|
||||||
def test_list_users(self):
|
def test_list_users(self):
|
||||||
'''
|
'''
|
||||||
Return a list of all users
|
Return a list of all users
|
||||||
'''
|
'''
|
||||||
self.assertTrue(pw_user.list_users())
|
mock_user = 'saltdude'
|
||||||
|
|
||||||
|
class MockData(object):
|
||||||
|
pw_name = mock_user
|
||||||
|
|
||||||
|
with patch('pwd.getpwall', MagicMock(return_value=[MockData()])):
|
||||||
|
self.assertEqual(pw_user.list_users(), [mock_user])
|
||||||
|
|
||||||
def test_rename(self):
|
def test_rename(self):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -98,7 +98,7 @@ class BotoElbTestCase(TestCase):
|
||||||
self.assertTrue(boto_elb.__salt__['boto_elb.exists'].called)
|
self.assertTrue(boto_elb.__salt__['boto_elb.exists'].called)
|
||||||
self.assertTrue(boto_elb.__salt__['boto_elb.create'].called)
|
self.assertTrue(boto_elb.__salt__['boto_elb.create'].called)
|
||||||
self.assertTrue(boto_elb.__salt__['state.single'].called)
|
self.assertTrue(boto_elb.__salt__['state.single'].called)
|
||||||
self.assertTrue(
|
self.assertFalse(
|
||||||
boto_elb.__salt__['boto_elb.get_attributes'].called
|
boto_elb.__salt__['boto_elb.get_attributes'].called
|
||||||
)
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
|
|
|
@ -139,7 +139,8 @@ class CronTestCase(TestCase):
|
||||||
cron.present(
|
cron.present(
|
||||||
name='foo',
|
name='foo',
|
||||||
hour='2',
|
hour='2',
|
||||||
user='root')
|
user='root',
|
||||||
|
identifier=None)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
get_crontab(),
|
get_crontab(),
|
||||||
('# Lines below here are managed by Salt, do not edit\n'
|
('# Lines below here are managed by Salt, do not edit\n'
|
||||||
|
@ -147,7 +148,7 @@ class CronTestCase(TestCase):
|
||||||
'* 2 * * * foo\n'
|
'* 2 * * * foo\n'
|
||||||
'# SALT_CRON_IDENTIFIER:2\n'
|
'# SALT_CRON_IDENTIFIER:2\n'
|
||||||
'* 2 * * * foo\n'
|
'* 2 * * * foo\n'
|
||||||
'* 2 * * * foo\n'))
|
'* 2 * * * foo'))
|
||||||
|
|
||||||
@patch('salt.modules.cron.raw_cron',
|
@patch('salt.modules.cron.raw_cron',
|
||||||
new=MagicMock(side_effect=get_crontab))
|
new=MagicMock(side_effect=get_crontab))
|
||||||
|
@ -196,214 +197,107 @@ class CronTestCase(TestCase):
|
||||||
new=MagicMock(side_effect=get_crontab))
|
new=MagicMock(side_effect=get_crontab))
|
||||||
@patch('salt.modules.cron._write_cron_lines',
|
@patch('salt.modules.cron._write_cron_lines',
|
||||||
new=MagicMock(side_effect=write_crontab))
|
new=MagicMock(side_effect=write_crontab))
|
||||||
def test_aissue_1072(self):
|
def test_multiline_comments_are_updated(self):
|
||||||
set_crontab(
|
set_crontab(
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'# I have a multi-line comment SALT_CRON_IDENTIFIER:1\n'
|
'# First crontab - single line comment SALT_CRON_IDENTIFIER:1\n'
|
||||||
'* 1 * * * foo'
|
'* 1 * * * foo'
|
||||||
)
|
)
|
||||||
cron.present(
|
cron.present(
|
||||||
name='foo',
|
name='foo',
|
||||||
hour='1',
|
hour='1',
|
||||||
comment='1I have a multi-line comment\n2about my script here.\n',
|
comment='First crontab\nfirst multi-line comment\n',
|
||||||
identifier='1',
|
identifier='1',
|
||||||
user='root')
|
user='root')
|
||||||
cron.present(
|
cron.present(
|
||||||
name='foo',
|
name='foo',
|
||||||
hour='1',
|
hour='1',
|
||||||
comment='3I have a multi-line comment\n3about my script here.\n',
|
comment='First crontab\nsecond multi-line comment\n',
|
||||||
|
identifier='1',
|
||||||
user='root')
|
user='root')
|
||||||
cron.present(
|
cron.present(
|
||||||
name='foo',
|
name='foo',
|
||||||
hour='1',
|
hour='1',
|
||||||
comment='I have a multi-line comment\nabout my script here.\n',
|
comment='Second crontab\nmulti-line comment\n',
|
||||||
identifier='2',
|
identifier='2',
|
||||||
user='root')
|
user='root')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
get_crontab(),
|
get_crontab(),
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'# 2about my script here. SALT_CRON_IDENTIFIER:1\n'
|
'# First crontab\n'
|
||||||
|
'# second multi-line comment SALT_CRON_IDENTIFIER:1\n'
|
||||||
'* 1 * * * foo\n'
|
'* 1 * * * foo\n'
|
||||||
'# I have a multi-line comment\n'
|
'# Second crontab\n'
|
||||||
'# about my script here. SALT_CRON_IDENTIFIER:2\n'
|
'# multi-line comment SALT_CRON_IDENTIFIER:2\n'
|
||||||
'* 1 * * * foo')
|
'* 1 * * * foo')
|
||||||
|
|
||||||
@patch('salt.modules.cron.raw_cron',
|
@patch('salt.modules.cron.raw_cron',
|
||||||
new=MagicMock(side_effect=get_crontab))
|
new=MagicMock(side_effect=get_crontab))
|
||||||
@patch('salt.modules.cron._write_cron_lines',
|
@patch('salt.modules.cron._write_cron_lines',
|
||||||
new=MagicMock(side_effect=write_crontab))
|
new=MagicMock(side_effect=write_crontab))
|
||||||
def test_issue_11935(self):
|
def test_existing_unmanaged_jobs_are_made_managed(self):
|
||||||
set_crontab(
|
set_crontab(
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'0 2 * * * find /var/www -type f '
|
'0 2 * * * foo'
|
||||||
'-mtime -7 -print0 | xargs -0 '
|
|
||||||
'clamscan -i --no-summary 2>/dev/null'
|
|
||||||
)
|
)
|
||||||
cmd = (
|
ret = cron._check_cron('root', 'foo', hour='2', minute='0')
|
||||||
'find /var/www -type f -mtime -7 -print0 '
|
self.assertEqual(ret, 'present')
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null'
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
||||||
)
|
self.assertEqual(ret['changes'], {'root': 'foo'})
|
||||||
self.assertEqual(cron._check_cron('root', cmd, hour='2', minute='0'),
|
self.assertEqual(ret['comment'], 'Cron foo updated')
|
||||||
'present')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='2')
|
|
||||||
self.assertEqual(ret['changes'], {})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null already present')
|
|
||||||
self.assertEqual(cron._check_cron('root', cmd, hour='3', minute='0'),
|
|
||||||
'update')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='3')
|
|
||||||
self.assertEqual(ret['changes'],
|
|
||||||
{'root': 'find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/null'})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null updated')
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
get_crontab(),
|
get_crontab(),
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'0 3 * * * find /var/www -type f -mtime -7 -print0 |'
|
'# SALT_CRON_IDENTIFIER:foo\n'
|
||||||
' xargs -0 clamscan -i --no-summary 2>/dev/null')
|
'0 2 * * * foo')
|
||||||
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
||||||
|
self.assertEqual(ret['changes'], {})
|
||||||
|
self.assertEqual(ret['comment'], 'Cron foo already present')
|
||||||
|
|
||||||
@patch('salt.modules.cron.raw_cron',
|
@patch('salt.modules.cron.raw_cron',
|
||||||
new=MagicMock(side_effect=get_crontab))
|
new=MagicMock(side_effect=get_crontab))
|
||||||
@patch('salt.modules.cron._write_cron_lines',
|
@patch('salt.modules.cron._write_cron_lines',
|
||||||
new=MagicMock(side_effect=write_crontab))
|
new=MagicMock(side_effect=write_crontab))
|
||||||
def test_issue_11935_with_id(self):
|
def test_existing_noid_jobs_are_updated_with_identifier(self):
|
||||||
set_crontab(
|
set_crontab(
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'# SALT_CRON_IDENTIFIER:1\n'
|
'# SALT_CRON_IDENTIFIER:NO ID SET\n'
|
||||||
'0 2 * * * find /var/www -type f '
|
'1 * * * * foo'
|
||||||
'-mtime -7 -print0 | xargs -0 '
|
|
||||||
'clamscan -i --no-summary 2>/dev/null'
|
|
||||||
)
|
)
|
||||||
cmd = (
|
ret = cron._check_cron('root', 'foo', minute=1)
|
||||||
'find /var/www -type f -mtime -7 -print0 '
|
self.assertEqual(ret, 'present')
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null'
|
ret = cron.present('foo', 'root', minute=1)
|
||||||
)
|
self.assertEqual(ret['changes'], {'root': 'foo'})
|
||||||
self.assertEqual(cron._check_cron(
|
self.assertEqual(ret['comment'], 'Cron foo updated')
|
||||||
'root', cmd, hour='2', minute='0', identifier=1), 'present')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='2', identifier='1')
|
|
||||||
self.assertEqual(ret['changes'], {})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null already present')
|
|
||||||
self.assertEqual(cron._check_cron(
|
|
||||||
'root', cmd, hour='3', minute='0', identifier='1'), 'update')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='3', identifier='1')
|
|
||||||
self.assertEqual(ret['changes'],
|
|
||||||
{'root': 'find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/null'})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null updated')
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
get_crontab(),
|
get_crontab(),
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'# SALT_CRON_IDENTIFIER:1\n'
|
'# SALT_CRON_IDENTIFIER:foo\n'
|
||||||
'0 3 * * * find /var/www -type f -mtime -7 -print0 |'
|
'1 * * * * foo')
|
||||||
' xargs -0 clamscan -i --no-summary 2>/dev/null')
|
|
||||||
|
|
||||||
@patch('salt.modules.cron.raw_cron',
|
@patch('salt.modules.cron.raw_cron',
|
||||||
new=MagicMock(side_effect=get_crontab))
|
new=MagicMock(side_effect=get_crontab))
|
||||||
@patch('salt.modules.cron._write_cron_lines',
|
@patch('salt.modules.cron._write_cron_lines',
|
||||||
new=MagicMock(side_effect=write_crontab))
|
new=MagicMock(side_effect=write_crontab))
|
||||||
def test_issue_11935_mixed(self):
|
def test_existing_duplicate_unmanaged_jobs_are_merged_and_given_id(self):
|
||||||
set_crontab(
|
set_crontab(
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
'0 2 * * * find /var/www -type f '
|
'0 2 * * * foo\n'
|
||||||
'-mtime -7 -print0 | xargs -0 '
|
'0 2 * * * foo'
|
||||||
'clamscan -i --no-summary 2>/dev/null'
|
|
||||||
)
|
)
|
||||||
cmd = (
|
ret = cron._check_cron('root', 'foo', hour='2', minute='0')
|
||||||
'find /var/www -type f -mtime -7 -print0 '
|
self.assertEqual(ret, 'present')
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null'
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
||||||
)
|
self.assertEqual(ret['changes'], {'root': 'foo'})
|
||||||
self.assertEqual(cron._check_cron('root', cmd, hour='2', minute='0'),
|
self.assertEqual(ret['comment'], 'Cron foo updated')
|
||||||
'present')
|
self.assertEqual(
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='2')
|
get_crontab(),
|
||||||
|
'# Lines below here are managed by Salt, do not edit\n'
|
||||||
|
'# SALT_CRON_IDENTIFIER:foo\n'
|
||||||
|
'0 2 * * * foo')
|
||||||
|
ret = cron.present('foo', 'root', minute='0', hour='2')
|
||||||
self.assertEqual(ret['changes'], {})
|
self.assertEqual(ret['changes'], {})
|
||||||
self.assertEqual(
|
self.assertEqual(ret['comment'], 'Cron foo already present')
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null already present')
|
|
||||||
self.assertEqual(cron._check_cron('root', cmd, hour='3', minute='0'),
|
|
||||||
'update')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='3')
|
|
||||||
self.assertEqual(ret['changes'],
|
|
||||||
{'root': 'find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/null'})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null updated')
|
|
||||||
self.assertEqual(
|
|
||||||
get_crontab(),
|
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
|
||||||
'0 3 * * * find /var/www -type f -mtime -7 -print0 |'
|
|
||||||
' xargs -0 clamscan -i --no-summary 2>/dev/null')
|
|
||||||
self.assertEqual(cron._check_cron(
|
|
||||||
'root', cmd, hour='2', minute='0', identifier='1'), 'update')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='2', identifier='1')
|
|
||||||
self.assertEqual(
|
|
||||||
ret['changes'],
|
|
||||||
{'root': 'find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/null'})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null updated')
|
|
||||||
self.assertEqual(cron._check_cron(
|
|
||||||
'root', cmd, hour='3', minute='0', identifier='1'), 'update')
|
|
||||||
ret = cron.present(cmd, 'root', minute='0', hour='3', identifier='1')
|
|
||||||
self.assertEqual(ret['changes'],
|
|
||||||
{'root': 'find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/null'})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 '
|
|
||||||
'| xargs -0 clamscan -i --no-summary 2>/dev/null updated')
|
|
||||||
self.assertEqual(
|
|
||||||
get_crontab(),
|
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
|
||||||
'# SALT_CRON_IDENTIFIER:1\n'
|
|
||||||
'0 3 * * * find /var/www -type f -mtime -7 -print0 |'
|
|
||||||
' xargs -0 clamscan -i --no-summary 2>/dev/null')
|
|
||||||
|
|
||||||
set_crontab(
|
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
|
||||||
'0 2 * * * find /var/www -type f '
|
|
||||||
'-mtime -7 -print0 | xargs -0 '
|
|
||||||
'clamscan -i --no-summary 2>/dev/null'
|
|
||||||
)
|
|
||||||
self.assertEqual(cron._check_cron(
|
|
||||||
'root', cmd + "a", hour='2', minute='0', identifier='1'), 'absent')
|
|
||||||
ret = cron.present(
|
|
||||||
cmd + "a", 'root', minute='0', hour='2', identifier='1')
|
|
||||||
self.assertEqual(
|
|
||||||
ret['changes'],
|
|
||||||
{'root': 'find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/nulla'})
|
|
||||||
self.assertEqual(
|
|
||||||
ret['comment'],
|
|
||||||
'Cron find /var/www -type f -mtime -7 -print0 | '
|
|
||||||
'xargs -0 clamscan -i --no-summary 2>/dev/nulla added '
|
|
||||||
'to root\'s crontab')
|
|
||||||
self.assertEqual(
|
|
||||||
get_crontab(),
|
|
||||||
'# Lines below here are managed by Salt, do not edit\n'
|
|
||||||
'0 2 * * *'
|
|
||||||
' find /var/www -type f -mtime -7 -print0'
|
|
||||||
' | xargs -0 clamscan -i --no-summary 2>/dev/null\n'
|
|
||||||
'# SALT_CRON_IDENTIFIER:1\n'
|
|
||||||
'0 2 * * *'
|
|
||||||
' find /var/www -type f -mtime -7 -print0'
|
|
||||||
' | xargs -0 clamscan -i --no-summary 2>/dev/nulla')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from integration import run_tests
|
from integration import run_tests
|
||||||
|
|
|
@ -22,7 +22,7 @@ ensure_in_syspath('../../')
|
||||||
from salt.states import openstack_config
|
from salt.states import openstack_config
|
||||||
|
|
||||||
openstack_config.__salt__ = {}
|
openstack_config.__salt__ = {}
|
||||||
openstack_config.__opts__ = {}
|
openstack_config.__opts__ = {'test': False}
|
||||||
|
|
||||||
|
|
||||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
|
|
|
@ -36,28 +36,43 @@ class RegTestCase(TestCase):
|
||||||
'''
|
'''
|
||||||
Test to set a registry entry.
|
Test to set a registry entry.
|
||||||
'''
|
'''
|
||||||
name = 'HKEY_CURRENT_USER\\SOFTWARE\\Salt\\version'
|
name = 'HKEY_CURRENT_USER\\SOFTWARE\\Salt'
|
||||||
value = '0.15.3'
|
vname = 'version'
|
||||||
|
vdata = '0.15.3'
|
||||||
|
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
'result': True,
|
'result': True,
|
||||||
'comment': '{0} is already configured'.format(name)}
|
'comment': '{0} in {1} is already configured'.format(vname, name)}
|
||||||
|
|
||||||
mock = MagicMock(side_effect=[{'vdata': value}, {'vdata': 'a'}, {'vdata': 'a'}])
|
mock_read = MagicMock(side_effect=[{'vdata': vdata, 'success': True},
|
||||||
|
{'vdata': 'a', 'success': True},
|
||||||
|
{'vdata': 'a', 'success': True}])
|
||||||
mock_t = MagicMock(return_value=True)
|
mock_t = MagicMock(return_value=True)
|
||||||
with patch.dict(reg.__salt__, {'reg.read_value': mock,
|
with patch.dict(reg.__salt__, {'reg.read_value': mock_read,
|
||||||
'reg.set_value': mock_t}):
|
'reg.set_value': mock_t}):
|
||||||
self.assertDictEqual(reg.present(name, value), ret)
|
self.assertDictEqual(reg.present(name,
|
||||||
|
vname=vname,
|
||||||
|
vdata=vdata), ret)
|
||||||
|
|
||||||
with patch.dict(reg.__opts__, {'test': True}):
|
with patch.dict(reg.__opts__, {'test': True}):
|
||||||
ret.update({'comment': '', 'result': None,
|
ret.update({'comment': '', 'result': None,
|
||||||
'changes': {'reg': 'configured to 0.15.3'}})
|
'changes': {'reg': {'Will add': {'Key': name,
|
||||||
self.assertDictEqual(reg.present(name, value), ret)
|
'Entry': vname,
|
||||||
|
'Value': vdata}}}})
|
||||||
|
self.assertDictEqual(reg.present(name,
|
||||||
|
vname=vname,
|
||||||
|
vdata=vdata), ret)
|
||||||
|
|
||||||
with patch.dict(reg.__opts__, {'test': False}):
|
with patch.dict(reg.__opts__, {'test': False}):
|
||||||
ret.update({'result': True})
|
ret.update({'comment': 'Added {0} to {0}'.format(name),
|
||||||
self.assertDictEqual(reg.present(name, value), ret)
|
'result': True,
|
||||||
|
'changes': {'reg': {'Added': {'Key': name,
|
||||||
|
'Entry': vname,
|
||||||
|
'Value': vdata}}}})
|
||||||
|
self.assertDictEqual(reg.present(name,
|
||||||
|
vname=vname,
|
||||||
|
vdata=vdata), ret)
|
||||||
|
|
||||||
# 'absent' function tests: 1
|
# 'absent' function tests: 1
|
||||||
|
|
||||||
|
@ -65,27 +80,35 @@ class RegTestCase(TestCase):
|
||||||
'''
|
'''
|
||||||
Test to remove a registry entry.
|
Test to remove a registry entry.
|
||||||
'''
|
'''
|
||||||
name = 'HKEY_CURRENT_USER\\SOFTWARE\\Salt\\version'
|
name = 'HKEY_CURRENT_USER\\SOFTWARE\\Salt'
|
||||||
|
vname = 'version'
|
||||||
|
|
||||||
ret = {'name': name,
|
ret = {'name': name,
|
||||||
'changes': {},
|
'changes': {},
|
||||||
'result': True,
|
'result': True,
|
||||||
'comment': '{0} is already absent'.format(name)}
|
'comment': '{0} is already absent'.format(name)}
|
||||||
|
|
||||||
mock = MagicMock(side_effect=[{'success': False}, {'success': True}, {'success': True}])
|
mock_read = MagicMock(side_effect=[{'success': False},
|
||||||
|
{'success': False},
|
||||||
|
{'success': True},
|
||||||
|
{'success': True}])
|
||||||
mock_t = MagicMock(return_value=True)
|
mock_t = MagicMock(return_value=True)
|
||||||
with patch.dict(reg.__salt__, {'reg.read_value': mock,
|
with patch.dict(reg.__salt__, {'reg.read_value': mock_read,
|
||||||
'reg.delete_value': mock_t}):
|
'reg.delete_value': mock_t}):
|
||||||
self.assertDictEqual(reg.absent(name), ret)
|
self.assertDictEqual(reg.absent(name, vname), ret)
|
||||||
|
|
||||||
with patch.dict(reg.__opts__, {'test': True}):
|
with patch.dict(reg.__opts__, {'test': True}):
|
||||||
ret.update({'comment': '', 'result': None,
|
ret.update({'comment': '', 'result': None,
|
||||||
'changes': {'reg': 'Removed {0}'.format(name)}})
|
'changes': {'reg': {'Will remove': {'Entry': vname,
|
||||||
self.assertDictEqual(reg.absent(name), ret)
|
'Key': name}}}})
|
||||||
|
self.assertDictEqual(reg.absent(name, vname), ret)
|
||||||
|
|
||||||
with patch.dict(reg.__opts__, {'test': False}):
|
with patch.dict(reg.__opts__, {'test': False}):
|
||||||
ret.update({'result': True})
|
ret.update({'result': True,
|
||||||
self.assertDictEqual(reg.absent(name), ret)
|
'changes': {'reg': {'Removed': {'Entry': vname,
|
||||||
|
'Key': name}}},
|
||||||
|
'comment': 'Removed {0} from {0}'.format(name)})
|
||||||
|
self.assertDictEqual(reg.absent(name, vname), ret)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Add table
Reference in a new issue