file.recurse: Do not convert octal mode string to int (#35309)

* Add integration test for #34945

* file.recurse: Do not convert octal mode string to int

When we run file.makedirs_perms to create the dest directory, we pass
through the mode to file.check_perms. However, file.check_perms expects
an octal string, not an int. This causes the initial directory to be
chmod'ed to the wrong mode. When there are files in the source
directory, file.recurse will invoke the file.directory state to manage
files/dirs in that directory, and this ends up correcting the mode as we
simply pass the dir_mode to it. However, when there are only directories
in the source directory, this never happens and the incorrect mode
remains on the destination directory.

Fixes #34945.
This commit is contained in:
Erik Johnson 2016-08-09 14:02:26 -05:00 committed by Nicole Thomas
parent 2efc1b333b
commit 243909f39d
3 changed files with 32 additions and 2 deletions

View file

@ -2335,8 +2335,7 @@ def recurse(name,
return _error(
ret, 'The path {0} exists and is not a directory'.format(name))
if not __opts__['test']:
__salt__['file.makedirs_perms'](
name, user, group, int(str(dir_mode), 8) if dir_mode else None)
__salt__['file.makedirs_perms'](name, user, group, dir_mode)
def add_comment(path, comment):
comments = ret['comment'].setdefault(path, [])

View file

@ -0,0 +1 @@
Hello world!

View file

@ -767,6 +767,36 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
finally:
shutil.rmtree(name, ignore_errors=True)
def test_recurse_issue_34945(self):
'''
This tests the case where the source dir for the file.recurse state
does not contain any files (only subdirectories), and the dir_mode is
being managed. For a long time, this corner case resulted in the top
level of the destination directory being created with the wrong initial
permissions, a problem that would be corrected later on in the
file.recurse state via running state.directory. However, the
file.directory state only gets called when there are files to be
managed in that directory, and when the source directory contains only
subdirectories, the incorrectly-set initial perms would not be
repaired.
This was fixed in https://github.com/saltstack/salt/pull/35309
'''
dir_mode = '2775'
issue_dir = 'issue-34945'
name = os.path.join(integration.TMP, issue_dir)
try:
ret = self.run_state('file.recurse',
name=name,
source='salt://' + issue_dir,
dir_mode=dir_mode)
self.assertSaltTrueReturn(ret)
actual_dir_mode = oct(stat.S_IMODE(os.stat(name).st_mode))[-4:]
self.assertEqual(dir_mode, actual_dir_mode)
finally:
shutil.rmtree(name, ignore_errors=True)
def test_replace(self):
'''
file.replace