mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #29540 from basepi/merge-forward-2015.8
[2015.8] Merge forward from 2015.5 to 2015.8
This commit is contained in:
commit
25d3a75d8c
10 changed files with 320 additions and 144 deletions
|
@ -303,12 +303,12 @@ Set up an initial profile at ``/etc/salt/cloud.profiles``:
|
|||
SubnetId: subnet-813d4bbf
|
||||
SecurityGroupId:
|
||||
- sg-750af413
|
||||
del_root_vol_on_destroy: True
|
||||
del_all_vol_on_destroy: True
|
||||
volumes:
|
||||
- { size: 10, device: /dev/sdf }
|
||||
- { size: 10, device: /dev/sdg, type: io1, iops: 1000 }
|
||||
- { size: 10, device: /dev/sdh, type: io1, iops: 1000 }
|
||||
del_root_vol_on_destroy: True
|
||||
del_all_vol_on_destroy: True
|
||||
tag: {'Environment': 'production', 'Role': 'database'}
|
||||
sync_after_install: grains
|
||||
|
||||
|
@ -354,6 +354,16 @@ The following settings are always required for EC2:
|
|||
Optional Settings
|
||||
=================
|
||||
|
||||
EC2 allows a userdata file to be passed to the instance to be created. This
|
||||
functionality was added to Salt in the 2015.5.0 release.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
my-ec2-config:
|
||||
# Pass userdata to the instance to be created
|
||||
userdata_file: /etc/salt/my-userdata-file
|
||||
|
||||
|
||||
EC2 allows a location to be set for servers to be deployed in. Availability
|
||||
zones exist inside regions, and may be added to increase specificity.
|
||||
|
||||
|
|
|
@ -150,6 +150,7 @@ can tweak.
|
|||
|
||||
.. admonition:: Note
|
||||
|
||||
All settings should be provided in lowercase
|
||||
All values should be provided in seconds
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ After=network.target
|
|||
[Service]
|
||||
LimitNOFILE=16384
|
||||
Type=notify
|
||||
NotifyAccess=all
|
||||
ExecStart=/usr/bin/salt-master
|
||||
KillMode=process
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ To use the EC2 cloud module, set up the cloud configuration at
|
|||
|
||||
driver: ec2
|
||||
|
||||
# Pass userdata to the instance to be created
|
||||
userdata_file: /etc/salt/my-userdata-file
|
||||
|
||||
:depends: requests
|
||||
'''
|
||||
# pylint: disable=invalid-name,function-redefined
|
||||
|
|
|
@ -1810,7 +1810,7 @@ def replace(path,
|
|||
r_data = mmap.mmap(r_file.fileno(),
|
||||
0,
|
||||
access=mmap.ACCESS_READ)
|
||||
except ValueError:
|
||||
except (ValueError, mmap.error):
|
||||
# size of file in /proc is 0, but contains data
|
||||
r_data = "".join(r_file)
|
||||
if search_only:
|
||||
|
|
|
@ -1022,7 +1022,7 @@ def set_known_host(user=None,
|
|||
if key:
|
||||
remote_host = {'hostname': hostname, 'enc': enc, 'key': key}
|
||||
|
||||
if hash_known_hosts or port == DEFAULT_SSH_PORT:
|
||||
if hash_known_hosts or port == DEFAULT_SSH_PORT or ':' in remote_host['hostname']:
|
||||
line = '{hostname} {enc} {key}\n'.format(**remote_host)
|
||||
else:
|
||||
remote_host['port'] = port
|
||||
|
|
|
@ -44,6 +44,7 @@ try:
|
|||
import win32api
|
||||
import win32file
|
||||
import win32security
|
||||
import win32con
|
||||
from pywintypes import error as pywinerror
|
||||
HAS_WINDOWS_MODULES = True
|
||||
except ImportError:
|
||||
|
@ -53,7 +54,7 @@ except ImportError:
|
|||
import salt.utils
|
||||
from salt.modules.file import (check_hash, # pylint: disable=W0611
|
||||
directory_exists, get_managed, mkdir, makedirs_, makedirs_perms,
|
||||
check_managed, check_managed_changes, check_perms, remove, source_list,
|
||||
check_managed, check_managed_changes, check_perms, source_list,
|
||||
touch, append, contains, contains_regex, contains_regex_multiline,
|
||||
contains_glob, find, psed, get_sum, _get_bkroot, _mkstemp_copy,
|
||||
get_hash, manage_file, file_exists, get_diff, list_backups,
|
||||
|
@ -81,7 +82,7 @@ def __virtual__():
|
|||
global check_perms, get_managed, makedirs_perms, manage_file
|
||||
global source_list, mkdir, __clean_tmp, makedirs_, file_exists
|
||||
global check_managed, check_managed_changes, check_file_meta
|
||||
global remove, append, _error, directory_exists, touch, contains
|
||||
global append, _error, directory_exists, touch, contains
|
||||
global contains_regex, contains_regex_multiline, contains_glob
|
||||
global find, psed, get_sum, check_hash, get_hash, delete_backup
|
||||
global get_diff, _get_flags, extract_hash, comment_line
|
||||
|
@ -101,7 +102,6 @@ def __virtual__():
|
|||
restore_backup = _namespaced_function(restore_backup, globals())
|
||||
delete_backup = _namespaced_function(delete_backup, globals())
|
||||
extract_hash = _namespaced_function(extract_hash, globals())
|
||||
remove = _namespaced_function(remove, globals())
|
||||
append = _namespaced_function(append, globals())
|
||||
check_perms = _namespaced_function(check_perms, globals())
|
||||
get_managed = _namespaced_function(get_managed, globals())
|
||||
|
@ -1045,6 +1045,68 @@ def set_mode(path, mode):
|
|||
return get_mode(path)
|
||||
|
||||
|
||||
def remove(path, force=False):
|
||||
'''
|
||||
Remove the named file or directory
|
||||
|
||||
:param str path: The path to the file or directory to remove.
|
||||
|
||||
:param bool force: Remove even if marked Read-Only
|
||||
|
||||
:return: True if successful, False if unsuccessful
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' file.remove C:\\Temp
|
||||
'''
|
||||
# This must be a recursive function in windows to properly deal with
|
||||
# Symlinks. The shutil.rmtree function will remove the contents of
|
||||
# the Symlink source in windows.
|
||||
|
||||
path = os.path.expanduser(path)
|
||||
|
||||
# Does the file/folder exists
|
||||
if not os.path.exists(path):
|
||||
return 'File/Folder not found: {0}'.format(path)
|
||||
|
||||
if not os.path.isabs(path):
|
||||
raise SaltInvocationError('File path must be absolute.')
|
||||
|
||||
# Remove ReadOnly Attribute
|
||||
if force:
|
||||
# Get current file attributes
|
||||
file_attributes = win32api.GetFileAttributes(path)
|
||||
win32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL)
|
||||
|
||||
try:
|
||||
if os.path.isfile(path):
|
||||
# A file and a symlinked file are removed the same way
|
||||
os.remove(path)
|
||||
elif is_link(path):
|
||||
# If it's a symlink directory, use the rmdir command
|
||||
os.rmdir(path)
|
||||
else:
|
||||
for name in os.listdir(path):
|
||||
item = '{0}\\{1}'.format(path, name)
|
||||
# If it's a normal directory, recurse to remove it's contents
|
||||
remove(item, force)
|
||||
|
||||
# rmdir will work now because the directory is empty
|
||||
os.rmdir(path)
|
||||
except (OSError, IOError) as exc:
|
||||
if force:
|
||||
# Reset attributes to the original if delete fails.
|
||||
win32api.SetFileAttributes(path, file_attributes)
|
||||
raise CommandExecutionError(
|
||||
'Could not remove {0!r}: {1}'.format(path, exc)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def symlink(src, link):
|
||||
'''
|
||||
Create a symbolic link to a file
|
||||
|
|
|
@ -434,7 +434,7 @@ def _clean_dir(root, keep, exclude_pat):
|
|||
try:
|
||||
os.remove(nfn)
|
||||
except OSError:
|
||||
shutil.rmtree(nfn)
|
||||
__salt__['file.remove'](nfn)
|
||||
|
||||
for roots, dirs, files in os.walk(root):
|
||||
for name in itertools.chain(dirs, files):
|
||||
|
@ -909,23 +909,16 @@ def symlink(
|
|||
return _error(ret, ((
|
||||
'File exists where the backup target {0} should go'
|
||||
).format(backupname)))
|
||||
elif os.path.isfile(backupname):
|
||||
os.remove(backupname)
|
||||
elif os.path.isdir(backupname):
|
||||
shutil.rmtree(backupname)
|
||||
else:
|
||||
return _error(ret, ((
|
||||
'Something exists where the backup target {0}'
|
||||
'should go'
|
||||
).format(backupname)))
|
||||
__salt__['file.remove'](backupname)
|
||||
os.rename(name, backupname)
|
||||
elif force:
|
||||
# Remove whatever is in the way
|
||||
if os.path.isfile(name):
|
||||
os.remove(name)
|
||||
if __salt__['file.is_link'](name):
|
||||
__salt__['file.remove'](name)
|
||||
ret['changes']['forced'] = 'Symlink was forcibly replaced'
|
||||
else:
|
||||
shutil.rmtree(name)
|
||||
__salt__['file.remove'](name)
|
||||
else:
|
||||
# Otherwise throw an error
|
||||
if os.path.isfile(name):
|
||||
|
@ -1001,7 +994,7 @@ def absent(name):
|
|||
ret['comment'] = 'Directory {0} is set for removal'.format(name)
|
||||
return ret
|
||||
try:
|
||||
shutil.rmtree(name)
|
||||
__salt__['file.remove'](name)
|
||||
ret['comment'] = 'Removed directory {0}'.format(name)
|
||||
ret['changes']['removed'] = name
|
||||
return ret
|
||||
|
@ -1760,28 +1753,19 @@ def directory(name,
|
|||
return _error(ret, ((
|
||||
'File exists where the backup target {0} should go'
|
||||
).format(backupname)))
|
||||
elif os.path.isfile(backupname):
|
||||
os.remove(backupname)
|
||||
elif os.path.islink(backupname):
|
||||
os.remove(backupname)
|
||||
elif os.path.isdir(backupname):
|
||||
shutil.rmtree(backupname)
|
||||
else:
|
||||
return _error(ret, ((
|
||||
'Something exists where the backup target {0}'
|
||||
'should go'
|
||||
).format(backupname)))
|
||||
__salt__['file.remove'](backupname)
|
||||
os.rename(name, backupname)
|
||||
elif force:
|
||||
# Remove whatever is in the way
|
||||
if os.path.isfile(name):
|
||||
os.remove(name)
|
||||
ret['changes']['forced'] = 'File was forcibly replaced'
|
||||
elif os.path.islink(name):
|
||||
os.remove(name)
|
||||
elif __salt__['file.is_link'](name):
|
||||
__salt__['file.remove'](name)
|
||||
ret['changes']['forced'] = 'Symlink was forcibly replaced'
|
||||
else:
|
||||
shutil.rmtree(name)
|
||||
__salt__['file.remove'](name)
|
||||
else:
|
||||
if os.path.isfile(name):
|
||||
return _error(
|
||||
|
@ -2206,7 +2190,7 @@ def recurse(name,
|
|||
merge_ret(path, _ret)
|
||||
return
|
||||
else:
|
||||
shutil.rmtree(path)
|
||||
__salt__['file.remove'](path)
|
||||
_ret['changes'] = {'diff': 'Replaced directory with a '
|
||||
'new file'}
|
||||
merge_ret(path, _ret)
|
||||
|
@ -3814,12 +3798,7 @@ def copy(
|
|||
elif not __opts__['test'] and changed:
|
||||
# Remove the destination to prevent problems later
|
||||
try:
|
||||
if os.path.islink(name):
|
||||
os.unlink(name)
|
||||
elif os.path.isfile(name):
|
||||
os.remove(name)
|
||||
else:
|
||||
shutil.rmtree(name)
|
||||
__salt__['file.remove'](name)
|
||||
except (IOError, OSError):
|
||||
return _error(
|
||||
ret,
|
||||
|
@ -3919,12 +3898,7 @@ def rename(name, source, force=False, makedirs=False):
|
|||
elif not __opts__['test']:
|
||||
# Remove the destination to prevent problems later
|
||||
try:
|
||||
if os.path.islink(name):
|
||||
os.unlink(name)
|
||||
elif os.path.isfile(name):
|
||||
os.remove(name)
|
||||
else:
|
||||
shutil.rmtree(name)
|
||||
__salt__['file.remove'](name)
|
||||
except (IOError, OSError):
|
||||
return _error(
|
||||
ret,
|
||||
|
|
|
@ -3,10 +3,16 @@
|
|||
Manage SVN repositories
|
||||
=======================
|
||||
|
||||
Manage repository checkouts via the svn vcs system:
|
||||
Manage repository checkouts via the svn vcs system. Note that subversion must
|
||||
be installed for these states to be available, so svn states should include a
|
||||
requisite to a pkg.installed state for the package which provides subversion
|
||||
(``subversion`` in most cases). Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
subversion:
|
||||
pkg.installed
|
||||
|
||||
http://unladen-swallow.googlecode.com/svn/trunk/:
|
||||
svn.latest:
|
||||
- target: /tmp/swallow
|
||||
|
|
|
@ -23,6 +23,7 @@ import yaml
|
|||
import salt.states.file as filestate
|
||||
from salt.exceptions import CommandExecutionError
|
||||
import salt
|
||||
import salt.utils
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
@ -139,7 +140,10 @@ class FileTestCase(TestCase):
|
|||
name = '/etc/grub.conf'
|
||||
target = '/boot/grub/grub.conf'
|
||||
user = 'salt'
|
||||
group = 'saltstack'
|
||||
if salt.utils.is_windows():
|
||||
group = 'salt'
|
||||
else:
|
||||
group = 'saltstack'
|
||||
|
||||
ret = {'name': name,
|
||||
'result': False,
|
||||
|
@ -148,44 +152,44 @@ class FileTestCase(TestCase):
|
|||
|
||||
mock_t = MagicMock(return_value=True)
|
||||
mock_f = MagicMock(return_value=False)
|
||||
mock_uid = MagicMock(side_effect=['', 'U12', 'U12', 'U12', 'U12',
|
||||
'U12', 'U12', 'U12', 'U12', 'U12'])
|
||||
mock_gid = MagicMock(side_effect=['', 'G12', 'G12', 'G12', 'G12',
|
||||
'G12', 'G12', 'G12', 'G12', 'G12'])
|
||||
mock_if = MagicMock(side_effect=[False, True, False, False, False,
|
||||
False, False, False])
|
||||
mock_dir = MagicMock(side_effect=[True, True, True, True, False, True,
|
||||
True, True, True, False, True, False])
|
||||
mock_ret = MagicMock(return_value=target)
|
||||
mock_empty = MagicMock(return_value='')
|
||||
mock_uid = MagicMock(return_value='U1001')
|
||||
mock_gid = MagicMock(return_value='g1001')
|
||||
mock_target = MagicMock(return_value=target)
|
||||
mock_user = MagicMock(return_value=user)
|
||||
mock_grp = MagicMock(return_value=group)
|
||||
mock_file = MagicMock(side_effect=[OSError, True])
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_if,
|
||||
'file.readlink': mock_ret,
|
||||
'file.get_user': mock_user,
|
||||
'file.get_group': mock_grp,
|
||||
'file.symlink': mock_file}):
|
||||
mock_os_error = MagicMock(side_effect=OSError)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t}):
|
||||
comt = ('Must provide name to file.symlink')
|
||||
ret.update({'comment': comt, 'name': ''})
|
||||
self.assertDictEqual(filestate.symlink('', target), ret)
|
||||
|
||||
comt = ('User salt does not exist. Group saltstack does not exist.')
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_empty,
|
||||
'file.group_to_gid': mock_empty}):
|
||||
comt = ('User {0} does not exist. Group {1} does not exist.'.format(user, group))
|
||||
ret.update({'comment': comt, 'name': name})
|
||||
self.assertDictEqual(filestate.symlink(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f}):
|
||||
with patch.dict(filestate.__opts__, {'test': True}):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('Symlink /etc/grub.conf to /boot/grub/grub.conf'
|
||||
' is set for creation')
|
||||
comt = ('Symlink {0} to {1}'
|
||||
' is set for creation').format(name, target)
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', mock_f):
|
||||
comt = ('Directory /etc for symlink is not present')
|
||||
|
@ -194,15 +198,28 @@ class FileTestCase(TestCase):
|
|||
user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_t,
|
||||
'file.readlink': mock_target}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
comt = ('Symlink {0} is present and owned by '
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
with patch.object(salt.states.file, '_check_symlink_ownership', mock_t):
|
||||
comt = ('Symlink {0} is present and owned by '
|
||||
'{1}:{2}'.format(name, user, group))
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(filestate.symlink(name, target,
|
||||
user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.object(os.path, 'isdir', mock_dir):
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_t):
|
||||
comt = ('File exists where the backup target SALT'
|
||||
' should go')
|
||||
|
@ -212,14 +229,13 @@ class FileTestCase(TestCase):
|
|||
group=group, backupname='SALT'),
|
||||
ret)
|
||||
|
||||
comt = ('Something exists where the backup target'
|
||||
' SALTshould go')
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group, backupname='SALT',
|
||||
force=True), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'isfile', mock_t):
|
||||
comt = ('File exists where the symlink {0} should be'
|
||||
.format(name))
|
||||
|
@ -228,30 +244,104 @@ class FileTestCase(TestCase):
|
|||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = ('Directory exists where the symlink {0}'
|
||||
' should be'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target,
|
||||
'file.symlink': mock_t,
|
||||
'user.info': mock_t,
|
||||
'file.lchown': mock_f}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_t):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('Unable to create new symlink {0} -> '
|
||||
'{1}: '.format(name, target))
|
||||
comt = ('File exists where the symlink {0} should be'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
comt = ('Created new symlink {0} -> '
|
||||
'{1}'.format(name, target))
|
||||
ret.update({'comment': comt, 'result': True,
|
||||
'changes': {'new': name}})
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target,
|
||||
'file.symlink': mock_t,
|
||||
'user.info': mock_t,
|
||||
'file.lchown': mock_f}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'exists', mock_f):
|
||||
comt = ('Directory exists where the symlink {0} should be'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target,
|
||||
'file.symlink': mock_os_error,
|
||||
'user.info': mock_t,
|
||||
'file.lchown': mock_f}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = ('Unable to create new symlink {0} -> '
|
||||
'{1}: '.format(name, target))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target,
|
||||
'file.symlink': mock_t,
|
||||
'user.info': mock_t,
|
||||
'file.lchown': mock_f,
|
||||
'file.get_user': mock_user,
|
||||
'file.get_group': mock_grp}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = 'Created new symlink {0} -> {1}'.format(name, target)
|
||||
ret.update({'comment': comt,
|
||||
'result': True,
|
||||
'changes': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.dict(filestate.__salt__, {'config.manage_mode': mock_t,
|
||||
'file.user_to_uid': mock_uid,
|
||||
'file.group_to_gid': mock_gid,
|
||||
'file.is_link': mock_f,
|
||||
'file.readlink': mock_target,
|
||||
'file.symlink': mock_t,
|
||||
'user.info': mock_t,
|
||||
'file.lchown': mock_f,
|
||||
'file.get_user': mock_empty,
|
||||
'file.get_group': mock_empty}):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(os.path, 'isdir', MagicMock(side_effect=[True, False])):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
comt = ('Created new symlink {0} -> {1}, '
|
||||
'but was unable to set ownership to '
|
||||
'{2}:{3}'.format(name, target, user, group))
|
||||
ret.update({'comment': comt,
|
||||
'result': False,
|
||||
'changes': {'new': name}})
|
||||
self.assertDictEqual(filestate.symlink
|
||||
(name, target, user=user,
|
||||
group=group), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
def test_absent(self):
|
||||
'''
|
||||
|
@ -317,7 +407,8 @@ class FileTestCase(TestCase):
|
|||
self.assertDictEqual(filestate.absent(name), ret)
|
||||
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(shutil, 'rmtree', mock_tree):
|
||||
with patch.dict(filestate.__salt__,
|
||||
{'file.remove': mock_tree}):
|
||||
comt = ('Removed directory {0}'.format(name))
|
||||
ret.update({'comment': comt, 'result': True,
|
||||
'changes': {'removed': name}})
|
||||
|
@ -601,8 +692,12 @@ class FileTestCase(TestCase):
|
|||
'file.group_to_gid': mock_gid,
|
||||
'file.stats': mock_f,
|
||||
'file.check_perms': mock_perms}):
|
||||
comt = ('User salt is not available Group saltstack'
|
||||
' is not available')
|
||||
if salt.utils.is_windows():
|
||||
comt = ('User salt is not available Group salt'
|
||||
' is not available')
|
||||
else:
|
||||
comt = ('User salt is not available Group saltstack'
|
||||
' is not available')
|
||||
ret.update({'comment': comt, 'name': name})
|
||||
self.assertDictEqual(filestate.directory(name, user=user,
|
||||
group=group), ret)
|
||||
|
@ -620,29 +715,20 @@ class FileTestCase(TestCase):
|
|||
True, True, True,
|
||||
False])):
|
||||
with patch.object(os.path, 'lexists', mock_t):
|
||||
with patch.object(os.path, 'islink', mock_f):
|
||||
with patch.object(os.path, 'isdir', mock_f):
|
||||
comt = ('File exists where the backup target'
|
||||
' A should go')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(filestate.directory
|
||||
(name, user=user,
|
||||
group=group,
|
||||
backupname='A'), ret)
|
||||
comt = ('File exists where the backup target'
|
||||
' A should go')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(filestate.directory
|
||||
(name, user=user,
|
||||
group=group,
|
||||
backupname='A'), ret)
|
||||
|
||||
comt = ('Something exists where the backup'
|
||||
' target Ashould go')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(filestate.directory
|
||||
(name, user=user,
|
||||
group=group, force=True,
|
||||
backupname='A'), ret)
|
||||
|
||||
comt = ('Specified location {0} exists and is a file'
|
||||
.format(name))
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(filestate.directory(name, user=user,
|
||||
group=group), ret)
|
||||
with patch.object(os.path, 'isfile', mock_t):
|
||||
comt = ('Specified location {0} exists and is a file'
|
||||
.format(name))
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(filestate.directory(name, user=user,
|
||||
group=group), ret)
|
||||
|
||||
with patch.object(os.path, 'islink', mock_t):
|
||||
comt = ('Specified location {0} exists and is a symlink'
|
||||
|
@ -1288,15 +1374,14 @@ class FileTestCase(TestCase):
|
|||
with patch.object(os.path, 'lexists', mock_t):
|
||||
with patch.dict(filestate.__opts__,
|
||||
{'test': False}):
|
||||
with patch.object(os.path, 'isfile', mock_f):
|
||||
with patch.object(os.path, 'islink',
|
||||
mock_io):
|
||||
ret.update({'comment': comt1,
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.copy
|
||||
(name, source,
|
||||
preserve=True,
|
||||
force=True), ret)
|
||||
with patch.dict(filestate.__salt__,
|
||||
{'file.remove': mock_io}):
|
||||
ret.update({'comment': comt1,
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.copy
|
||||
(name, source,
|
||||
preserve=True,
|
||||
force=True), ret)
|
||||
|
||||
with patch.object(os.path, 'isfile', mock_t):
|
||||
ret.update({'comment': comt2,
|
||||
|
@ -1361,14 +1446,14 @@ class FileTestCase(TestCase):
|
|||
|
||||
mock_t = MagicMock(return_value=True)
|
||||
mock_f = MagicMock(return_value=False)
|
||||
mock_lex = MagicMock(side_effect=[False, True, True, True, True, True,
|
||||
True, True, False, True, False, True,
|
||||
False, True, False])
|
||||
|
||||
mock_lex = MagicMock(side_effect=[False, True, True])
|
||||
with patch.object(os.path, 'isabs', mock_f):
|
||||
comt = ('Specified file {0} is not an absolute path'.format(name))
|
||||
ret.update({'comment': comt, 'name': name})
|
||||
self.assertDictEqual(filestate.rename(name, source), ret)
|
||||
|
||||
mock_lex = MagicMock(return_value=False)
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
comt = ('Source file "{0}" has already been moved out of '
|
||||
|
@ -1376,47 +1461,81 @@ class FileTestCase(TestCase):
|
|||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(filestate.rename(name, source), ret)
|
||||
|
||||
mock_lex = MagicMock(side_effect=[True, True, True])
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
comt = ('The target file "{0}" exists and will not be '
|
||||
'overwritten'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.rename(name, source), ret)
|
||||
|
||||
mock_lex = MagicMock(side_effect=[True, True, True])
|
||||
mock_rem = MagicMock(side_effect=IOError)
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
comt = ('Failed to delete "{0}" in preparation for '
|
||||
'forced move'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(filestate.rename(name, source,
|
||||
force=True), ret)
|
||||
with patch.dict(filestate.__salt__,
|
||||
{'file.remove': mock_rem}):
|
||||
ret.update({'name': name,
|
||||
'comment': comt,
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.rename(name, source,
|
||||
force=True), ret)
|
||||
|
||||
mock_lex = MagicMock(side_effect=[True, False, False])
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
with patch.dict(filestate.__opts__, {'test': True}):
|
||||
comt = ('File "{0}" is set to be moved to "{1}"'
|
||||
.format(source, name))
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
ret.update({'name': name,
|
||||
'comment': comt,
|
||||
'result': None})
|
||||
self.assertDictEqual(filestate.rename(name, source), ret)
|
||||
|
||||
mock_lex = MagicMock(side_effect=[True, False, False])
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
with patch.object(os.path, 'isdir', mock_f):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
comt = ('The target directory /tmp is not present')
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
ret.update({'name': name,
|
||||
'comment': comt,
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.rename(name, source),
|
||||
ret)
|
||||
|
||||
mock_lex = MagicMock(side_effect=[True, False, False])
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'islink', mock_f):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(shutil, 'move',
|
||||
MagicMock(side_effect=[IOError,
|
||||
True])):
|
||||
MagicMock(side_effect=IOError)):
|
||||
comt = ('Failed to move "{0}" to "{1}"'
|
||||
.format(source, name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
ret.update({'name': name,
|
||||
'comment': comt,
|
||||
'result': False})
|
||||
self.assertDictEqual(filestate.rename(name,
|
||||
source),
|
||||
ret)
|
||||
|
||||
mock_lex = MagicMock(side_effect=[True, False, False])
|
||||
with patch.object(os.path, 'isabs', mock_t):
|
||||
with patch.object(os.path, 'lexists', mock_lex):
|
||||
with patch.object(os.path, 'isdir', mock_t):
|
||||
with patch.object(os.path, 'islink', mock_f):
|
||||
with patch.dict(filestate.__opts__, {'test': False}):
|
||||
with patch.object(shutil, 'move', MagicMock()):
|
||||
comt = ('Moved "{0}" to "{1}"'.format(source,
|
||||
name))
|
||||
ret.update({'comment': comt, 'result': True,
|
||||
ret.update({'name': name,
|
||||
'comment': comt,
|
||||
'result': True,
|
||||
'changes': {name: source}})
|
||||
self.assertDictEqual(filestate.rename(name,
|
||||
source),
|
||||
|
|
Loading…
Add table
Reference in a new issue