Skip to content

Commit

Permalink
Merge pull request #34432 from twangboy/fix_file.append
Browse files Browse the repository at this point in the history
Fix file.append
  • Loading branch information
thatch45 committed Jul 5, 2016
2 parents 91e095b + 13f11fd commit 9e15337
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 109 deletions.
8 changes: 4 additions & 4 deletions salt/modules/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -2472,11 +2472,11 @@ def append(path, *args, **kwargs):
if ofile.read(len(linesep)) != linesep:
ofile.seek(0, os.SEEK_END)
ofile.write(linesep)

# Append lines in text mode
with salt.utils.fopen(path, 'r+') as ofile:
ofile.seek(0, os.SEEK_END)
for line in args:
ofile.write('{0}\n'.format(line))
with salt.utils.fopen(path, 'a') as ofile:
for new_line in args:
ofile.write('{0}{1}'.format(new_line, os.linesep))

return 'Wrote {0} lines to "{1}"'.format(len(args), path)

Expand Down
51 changes: 26 additions & 25 deletions salt/states/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -3459,12 +3459,16 @@ def append(name,
.. versionadded:: 0.9.5
'''
name = os.path.expanduser(name)
ret = {'name': name,
'changes': {},
'result': False,
'comment': ''}

ret = {'name': name, 'changes': {}, 'result': False, 'comment': ''}
if not name:
return _error(ret, 'Must provide name to file.append')

name = os.path.expanduser(name)

if sources is None:
sources = []

Expand Down Expand Up @@ -3515,70 +3519,67 @@ def append(name,

with salt.utils.fopen(name, 'rb') as fp_:
slines = fp_.readlines()
slines = [item.rstrip() for item in slines]

count = 0
test_lines = []

append_lines = []
try:
for chunk in text:
if ignore_whitespace:
if __salt__['file.search'](
name,
salt.utils.build_whitespace_split_regex(chunk),
multiline=True):
name,
salt.utils.build_whitespace_split_regex(chunk),
multiline=True):
continue
elif __salt__['file.search'](
name,
chunk,
multiline=True):
continue

lines = chunk.splitlines()
for line_item in chunk.splitlines():
append_lines.append('{0}'.format(line_item))

for line in lines:
if __opts__['test']:
ret['comment'] = 'File {0} is set to be updated'.format(name)
ret['result'] = None
test_lines.append('{0}\n'.format(line))
else:
__salt__['file.append'](name, line)
count += 1
except TypeError:
return _error(ret, 'No text found to append. Nothing appended')

if __opts__['test']:
nlines = slines + test_lines
ret['comment'] = 'File {0} is set to be updated'.format(name)
ret['result'] = None
nlines = list(slines)
nlines.extend(append_lines)
if slines != nlines:
if not salt.utils.istextfile(name):
ret['changes']['diff'] = 'Replace binary file'
else:
# Changes happened, add them
ret['changes']['diff'] = (
''.join(difflib.unified_diff(slines, nlines))
'\n'.join(difflib.unified_diff(slines, nlines))
)
else:
ret['comment'] = 'File {0} is in correct state'.format(name)
ret['result'] = True
return ret

if append_lines:
__salt__['file.append'](name, args=append_lines)
ret['comment'] = 'Appended {0} lines'.format(len(append_lines))
else:
ret['comment'] = 'File {0} is in correct state'.format(name)

with salt.utils.fopen(name, 'rb') as fp_:
nlines = fp_.readlines()
nlines = [item.rstrip(os.linesep) for item in nlines]

if slines != nlines:
if not salt.utils.istextfile(name):
ret['changes']['diff'] = 'Replace binary file'
else:
# Changes happened, add them
ret['changes']['diff'] = (
''.join(difflib.unified_diff(slines, nlines))
)
'\n'.join(difflib.unified_diff(slines, nlines)))

if count:
ret['comment'] = 'Appended {0} lines'.format(count)
else:
ret['comment'] = 'File {0} is in correct state'.format(name)
ret['result'] = True

return ret


Expand Down
80 changes: 0 additions & 80 deletions tests/unit/states/file_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1032,86 +1032,6 @@ def test_uncomment(self):
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(filestate.uncomment(name, regex), ret)

# 'append' function tests: 1

def test_append(self):
'''
Test to ensure that some text appears at the end of a file.
'''
name = '/etc/motd'
source = ['salt://motd/hr-messages.tmpl']
sources = ['salt://motd/devops-messages.tmpl']
text = ['Trust no one unless you have eaten much salt with him.']

ret = {'name': name,
'result': False,
'comment': '',
'changes': {}}

comt = ('Must provide name to file.append')
ret.update({'comment': comt, 'name': ''})
self.assertDictEqual(filestate.append(''), ret)

comt = ('source and sources are mutually exclusive')
ret.update({'comment': comt, 'name': name})
self.assertDictEqual(filestate.append(name, source=source,
sources=sources), ret)

mock_t = MagicMock(return_value=True)
mock_f = MagicMock(return_value=False)
mock_err = MagicMock(side_effect=[TypeError, True, True])
with patch.dict(filestate.__salt__,
{'file.directory_exists': mock_f,
'file.makedirs': mock_t,
'file.stats': mock_f,
'cp.get_template': mock_f,
'file.contains_regex_multiline': mock_err,
'file.search': mock_err}):
with patch.object(os.path, 'isdir', mock_t):
comt = ('The following files will be changed:\n/etc:'
' directory - new\n')
ret.update({'comment': comt, 'name': name})
self.assertDictEqual(filestate.append(name, makedirs=True), ret)

with patch.object(os.path, 'isabs', mock_f):
comt = ('Specified file {0} is not an absolute path'
.format(name))
ret.update({'comment': comt})
self.assertDictEqual(filestate.append(name), ret)

with patch.object(os.path, 'isabs', mock_t):
with patch.object(os.path, 'exists', mock_t):
comt = ("Failed to load template file {0}".format(source))
ret.update({'comment': comt, 'name': source, 'data': []})
self.assertDictEqual(filestate.append(name, source=source),
ret)

ret.pop('data', None)
ret.update({'name': name})
with patch.object(salt.utils, 'fopen',
MagicMock(mock_open(read_data=''))):
comt = ('No text found to append. Nothing appended')
ret.update({'comment': comt})
self.assertDictEqual(filestate.append(name, text=text),
ret)

with patch.object(salt.utils, 'istextfile', mock_f):
with patch.dict(filestate.__opts__, {'test': True}):
change = {'diff': 'Replace binary file'}
ret.update({'comment': '', 'result': None,
'changes': change})
self.assertDictEqual(filestate.append
(name, text=text), ret)

with patch.dict(filestate.__opts__,
{'test': False}):
comt = ('File {0} is in correct state'
.format(name))
ret.update({'comment': comt, 'result': True,
'changes': {}})
self.assertDictEqual(filestate.append
(name, text=text), ret)

# 'prepend' function tests: 1

def test_prepend(self):
Expand Down

0 comments on commit 9e15337

Please sign in to comment.