ansible: _remote_chmod() / _fixup_perms2() can be called sometimes.

It's used at least by the copy module, even though the result is still
mostly a no-op. _remote_chmod() doesn't accept octal mode, it accepts
symbolic mode. So implement a symbolic parser in helpers.py.
wip-fakessh-exit-status
David Wilson 6 years ago
parent 33781aba2c
commit 83f2862431

@ -197,8 +197,8 @@ class Connection(ansible.plugins.connection.ConnectionBase):
:returns:
(return code, stdout bytes, stderr bytes)
"""
return self.py_call(ansible_mitogen.helpers.exec_command,
cast(cmd), cast(in_data))
return self.call(ansible_mitogen.helpers.exec_command,
cast(cmd), cast(in_data))
def fetch_file(self, in_path, out_path):
"""
@ -210,8 +210,8 @@ class Connection(ansible.plugins.connection.ConnectionBase):
:param str out_path:
Local filesystem path to write.
"""
output = self.py_call(ansible_mitogen.helpers.read_path,
cast(in_path))
output = self.call(ansible_mitogen.helpers.read_path,
cast(in_path))
ansible_mitogen.helpers.write_path(out_path, output)
def put_file(self, in_path, out_path):
@ -224,5 +224,5 @@ class Connection(ansible.plugins.connection.ConnectionBase):
:param str out_path:
Remote filesystem path to write.
"""
self.py_call(ansible_mitogen.helpers.write_path, cast(out_path),
ansible_mitogen.helpers.read_path(in_path))
self.call(ansible_mitogen.helpers.write_path, cast(out_path),
ansible_mitogen.helpers.read_path(in_path))

@ -26,8 +26,11 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import json
import operator
import os
import pwd
import re
import stat
import subprocess
import time
@ -165,3 +168,59 @@ def write_path(path, s):
Writes bytes `s` to a filesystem `path`.
"""
open(path, 'wb').write(s)
CHMOD_CLAUSE_PAT = re.compile(r'([uoga]?)([+\-=])([ugo]|[rwx]*)')
CHMOD_MASKS = {
'u': stat.S_IRWXU,
'g': stat.S_IRWXG,
'o': stat.S_IRWXO,
'a': (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO),
}
CHMOD_BITS = {
'u': {'r':stat.S_IRUSR, 'w':stat.S_IWUSR, 'x':stat.S_IXUSR},
'g': {'r':stat.S_IRGRP, 'w':stat.S_IWGRP, 'x':stat.S_IXGRP},
'o': {'r':stat.S_IROTH, 'w':stat.S_IWOTH, 'x':stat.S_IXOTH},
'a': {
'r': (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH),
'w': (stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH),
'x': (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
}
}
def or_(it):
return reduce(operator.or_, it, 0)
def apply_mode_spec(spec, mode):
for clause in spec.split(','):
match = CHMOD_CLAUSE_PAT.match(clause)
who, op, perms = match.groups()
mask = CHMOD_MASKS[who]
bits = CHMOD_BITS[who]
for ch in who or 'a':
cur_perm_bits = mode & mask
new_perm_bits = or_(bits[p] for p in perms)
mode &= ~mask
if op == '=':
mode |= new_perm_bits
elif op == '+':
mode |= new_perm_bits | cur_per_bits
else:
mode |= cur_perm_bits & ~new_perm_bits
return mode
def set_file_mode(path, spec):
"""
Update the permissions of a file using the same syntax as chmod(1).
"""
mode = os.stat(path).st_mode
if spec.is_digit():
new_mode = int(spec, 8)
else:
new_mode = apply_mode_spec(spec, mode)
os.chmod(path, new_mode)

@ -117,11 +117,14 @@ class ActionModuleMixin(ansible.plugins.action.ActionBase):
def _fixup_perms2(self, remote_paths, remote_user=None, execute=True):
# replaces 83 lines
assert False, "_fixup_perms2() should never be called."
if not execute:
return self._remote_chmod(remote_paths, mode='u+x')
# Do nothing unless request was to set the execute bit.
return self.COMMAND_RESULT.copy()
def _remote_chmod(self, paths, mode, sudoable=False):
return self.fake_shell(lambda: mitogen.master.Select.all(
self._connection.call_async(os.chmod, path, mode)
self._connection.call_async(helpers.set_file_mode, path, mode)
for path in paths
))

Loading…
Cancel
Save