from __future__ import (absolute_import, division, print_function) __metaclass__ = type import os from ansible.errors import AnsibleError, AnsibleAction, AnsibleActionFail, AnsibleActionSkip, AnsibleConnectionFailure from ansible.module_utils._text import to_native, to_bytes from ansible.plugins.action import ActionBase from ansible.utils.cmd_functions import run_cmd class ActionModule(ActionBase): TRANSFERS_FILES = False DECOMPRESSORS = { 'application/gzip': 'gunzip', 'application/zstd': 'unzstd', 'application/x-bzip2': 'bunzip2', 'application/x-xz': 'unxz', } def _get_decompressor_for_file(self, file): try: rc, out, err = run_cmd('file --mime-type --mime-encoding %s' % (file)) if rc != 0: raise Exception('unable to read mime-type of file: %s' % (file)) out = to_native(out, errors='surrogate_or_strict') mimetype = out.rsplit(':', 1)[1].split(';')[0] return self.DECOMPRESSORS.get(mimetype.strip(), 'cat') except Exception as e: raise AnsibleActionFail(to_native(e)) def run(self, tmp=None, task_vars=None): if task_vars is None: task_vars = dict() result = super(ActionModule, self).run(tmp, task_vars) del tmp # tmp no longer has any effect try: if self._play_context.check_mode: raise AnsibleActionSkip('Check mode is not supported for this task.') result['changed'] = True source = to_native(self._task.args.get('src', ''), errors='surrogate_or_strict') destination = to_native(self._task.args.get('dest', ''), errors='surrogate_or_strict') decompressor = self._get_decompressor_for_file(source) try: source = self._loader.get_real_file(self._find_needle('files', source), decrypt=False) with open(to_bytes(source, errors='surrogate_or_strict'), 'rb') as f: source = to_bytes(f.read(), nonstring='passthru') except AnsibleError as e: raise AnsibleActionFail(to_native(e)) result.update(self._low_level_execute_command('%s > %s' % (decompressor, destination), in_data=source)) # workaround for gzip trailing garbage handling if 'rc' in result and result['rc'] == 2: if 'stderr' in result and 'decompression OK' in result['stderr']: result['rc'] = 0 self._fixup_perms2((destination), execute=False) except AnsibleAction as e: result.update(e.result) return result