コード例 #1
0
ファイル: assemble.py プロジェクト: ernstp/ansible
    def run(self, tmp=None, task_vars=None):

        self._supports_check_mode = False

        result = super(ActionModule, self).run(tmp, task_vars)

        if task_vars is None:
            task_vars = dict()

        src = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        delimiter = self._task.args.get('delimiter', None)
        remote_src = self._task.args.get('remote_src', 'yes')
        regexp = self._task.args.get('regexp', None)
        follow = self._task.args.get('follow', False)
        ignore_hidden = self._task.args.get('ignore_hidden', False)
        decrypt = self._task.args.get('decrypt', True)

        if src is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
            return result

        if boolean(remote_src, strict=False):
            result.update(self._execute_module(tmp=tmp, task_vars=task_vars))
            return result
        else:
            try:
                src = self._find_needle('files', src)
            except AnsibleError as e:
                result['failed'] = True
                result['msg'] = to_native(e)
                return result

        if not tmp:
            tmp = self._make_tmp_path()

        if not os.path.isdir(src):
            result['failed'] = True
            result['msg'] = u"Source (%s) is not a directory" % src
            return result

        _re = None
        if regexp is not None:
            _re = re.compile(regexp)

        # Does all work assembling the file
        path = self._assemble_from_fragments(src, delimiter, _re, ignore_hidden, decrypt)

        path_checksum = checksum_s(path)
        dest = self._remote_expand_user(dest)
        dest_stat = self._execute_remote_stat(dest, all_vars=task_vars, follow=follow, tmp=tmp)

        diff = {}

        # setup args for running modules
        new_module_args = self._task.args.copy()

        # clean assemble specific options
        for opt in ['remote_src', 'regexp', 'delimiter', 'ignore_hidden', 'decrypt']:
            if opt in new_module_args:
                del new_module_args[opt]

        new_module_args.update(
            dict(
                dest=dest,
                original_basename=os.path.basename(src),
            )
        )

        if path_checksum != dest_stat['checksum']:

            if self._play_context.diff:
                diff = self._get_diff_data(dest, path, task_vars)

            remote_path = self._connection._shell.join_path(tmp, 'src')
            xfered = self._transfer_file(path, remote_path)

            # fix file permissions when the copy is done as a different user
            self._fixup_perms2((tmp, remote_path))

            new_module_args.update(dict(src=xfered,))

            res = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False)
            if diff:
                res['diff'] = diff
            result.update(res)
        else:
            result.update(self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))

        self._remove_tmp_path(tmp)

        return result
コード例 #2
0
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for template operations '''

        source = self._task.args.get('src', None)
        dest   = self._task.args.get('dest', None)
        faf    = self._task.first_available_file

        if (source is None and faf is not None) or dest is None:
            return dict(failed=True, msg="src and dest are required")

        if tmp is None:
            tmp = self._make_tmp_path()

        if faf:
            source = self._get_first_available_file(faf, task_vars.get('_original_file', None, 'templates'))
            if source is None:
                return dict(failed=True, msg="could not find src in first_available_file list")
        else:
            if self._task._role is not None:
                source = self._loader.path_dwim_relative(self._task._role._role_path, 'templates', source)
            else:
                source = self._loader.path_dwim_relative(self._loader.get_basedir(), 'templates', source)

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            with open(source, 'r') as f:
                template_data = to_unicode(f.read())

            try:
                template_uid = pwd.getpwuid(os.stat(source).st_uid).pw_name
            except:
                template_uid = os.stat(source).st_uid

            temp_vars = task_vars.copy()
            temp_vars['template_host']     = os.uname()[1]
            temp_vars['template_path']     = source
            temp_vars['template_mtime']    = datetime.datetime.fromtimestamp(os.path.getmtime(source))
            temp_vars['template_uid']      = template_uid
            temp_vars['template_fullpath'] = os.path.abspath(source)
            temp_vars['template_run_date'] = datetime.datetime.now()

            managed_default = C.DEFAULT_MANAGED_STR
            managed_str = managed_default.format(
                host = temp_vars['template_host'],
                uid  = temp_vars['template_uid'],
                file = to_bytes(temp_vars['template_path'])
            )
            temp_vars['ansible_managed'] = time.strftime(
                managed_str,
                time.localtime(os.path.getmtime(source))
            )

            # Create a new searchpath list to assign to the templar environment's file
            # loader, so that it knows about the other paths to find template files
            searchpath = [self._loader._basedir, os.path.dirname(source)]
            if self._task._role is not None:
                searchpath.insert(1, C.DEFAULT_ROLES_PATH)
                searchpath.insert(1, self._task._role._role_path)

            self._templar.environment.loader.searchpath = searchpath

            old_vars = self._templar._available_variables
            self._templar.set_available_variables(temp_vars)
            resultant = self._templar.template(template_data, preserve_trailing_newlines=True, escape_backslashes=False, convert_data=False)
            self._templar.set_available_variables(old_vars)
        except Exception as e:
            return dict(failed=True, msg=type(e).__name__ + ": " + str(e))

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(dest, task_vars, not directory_prepended, source=source)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            return remote_checksum

        diff = {}
        new_module_args = self._task.args.copy()

        if local_checksum != remote_checksum:
            dest_contents = ''

            # if showing diffs, we need to get the remote value
            if self._play_context.diff:
                diff = self._get_diff_data(dest, resultant, task_vars, source_file=False)

            if not self._play_context.check_mode: # do actual work thorugh copy
                xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)

                # fix file permissions when the copy is done as a different user
                if self._play_context.become and self._play_context.become_user != 'root':
                    self._remote_chmod('a+r', xfered)

                # run the copy module
                new_module_args.update(
                   dict(
                       src=xfered,
                       dest=dest,
                       original_basename=os.path.basename(source),
                       follow=True,
                    ),
                )
                result = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars)
            else:
                result=dict(changed=True)

            if result.get('changed', False) and self._play_context.diff:
                result['diff'] = diff
            #    result['diff'] = dict(before=dest_contents, after=resultant, before_header=dest, after_header=source)

            return result

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ),
            )

            return self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars)
コード例 #3
0
ファイル: fetch.py プロジェクト: awiddersheim/ansible
    def run(self, tmp=None, task_vars=None):
        ''' handler for fetch operations '''
        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:
                result['skipped'] = True
                result['msg'] = 'check mode not (yet) supported for this module'
                return result

            source = self._task.args.get('src', None)
            dest = self._task.args.get('dest', None)
            flat = boolean(self._task.args.get('flat'), strict=False)
            fail_on_missing = boolean(self._task.args.get('fail_on_missing', True), strict=False)
            validate_checksum = boolean(self._task.args.get('validate_checksum',
                                                            self._task.args.get('validate_md5', True)),
                                        strict=False)

            # validate source and dest are strings FIXME: use basic.py and module specs
            if not isinstance(source, string_types):
                result['msg'] = "Invalid type supplied for source option, it must be a string"

            if not isinstance(dest, string_types):
                result['msg'] = "Invalid type supplied for dest option, it must be a string"

            # validate_md5 is the deprecated way to specify validate_checksum
            if 'validate_md5' in self._task.args and 'validate_checksum' in self._task.args:
                result['msg'] = "validate_checksum and validate_md5 cannot both be specified"

            if 'validate_md5' in self._task.args:
                display.deprecated('Use validate_checksum instead of validate_md5', version='2.8')

            if source is None or dest is None:
                result['msg'] = "src and dest are required"

            if result.get('msg'):
                result['failed'] = True
                return result

            source = self._connection._shell.join_path(source)
            source = self._remote_expand_user(source)

            remote_checksum = None
            if not self._play_context.become:
                # calculate checksum for the remote file, don't bother if using become as slurp will be used
                # Force remote_checksum to follow symlinks because fetch always follows symlinks
                remote_checksum = self._remote_checksum(source, all_vars=task_vars, follow=True)

            # use slurp if permissions are lacking or privilege escalation is needed
            remote_data = None
            if remote_checksum in ('1', '2', None):
                slurpres = self._execute_module(module_name='slurp', module_args=dict(src=source), task_vars=task_vars)
                if slurpres.get('failed'):
                    if not fail_on_missing and (slurpres.get('msg').startswith('file not found') or remote_checksum == '1'):
                        result['msg'] = "the remote file does not exist, not transferring, ignored"
                        result['file'] = source
                        result['changed'] = False
                    else:
                        result.update(slurpres)
                    return result
                else:
                    if slurpres['encoding'] == 'base64':
                        remote_data = base64.b64decode(slurpres['content'])
                    if remote_data is not None:
                        remote_checksum = checksum_s(remote_data)
                    # the source path may have been expanded on the
                    # target system, so we compare it here and use the
                    # expanded version if it's different
                    remote_source = slurpres.get('source')
                    if remote_source and remote_source != source:
                        source = remote_source

            # calculate the destination name
            if os.path.sep not in self._connection._shell.join_path('a', ''):
                source = self._connection._shell._unquote(source)
                source_local = source.replace('\\', '/')
            else:
                source_local = source

            dest = os.path.expanduser(dest)
            if flat:
                if os.path.isdir(to_bytes(dest, errors='surrogate_or_strict')) and not dest.endswith(os.sep):
                    result['msg'] = "dest is an existing directory, use a trailing slash if you want to fetch src into that directory"
                    result['file'] = dest
                    result['failed'] = True
                    return result
                if dest.endswith(os.sep):
                    # if the path ends with "/", we'll use the source filename as the
                    # destination filename
                    base = os.path.basename(source_local)
                    dest = os.path.join(dest, base)
                if not dest.startswith("/"):
                    # if dest does not start with "/", we'll assume a relative path
                    dest = self._loader.path_dwim(dest)
            else:
                # files are saved in dest dir, with a subdir for each host, then the filename
                if 'inventory_hostname' in task_vars:
                    target_name = task_vars['inventory_hostname']
                else:
                    target_name = self._play_context.remote_addr
                dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name, source_local)

            dest = dest.replace("//", "/")

            if remote_checksum in ('0', '1', '2', '3', '4', '5'):
                result['changed'] = False
                result['file'] = source
                if remote_checksum == '0':
                    result['msg'] = "unable to calculate the checksum of the remote file"
                elif remote_checksum == '1':
                    result['msg'] = "the remote file does not exist"
                elif remote_checksum == '2':
                    result['msg'] = "no read permission on remote file"
                elif remote_checksum == '3':
                    result['msg'] = "remote file is a directory, fetch cannot work on directories"
                elif remote_checksum == '4':
                    result['msg'] = "python isn't present on the system.  Unable to compute checksum"
                elif remote_checksum == '5':
                    result['msg'] = "stdlib json or simplejson was not found on the remote machine. Only the raw module can work without those installed"
                # Historically, these don't fail because you may want to transfer
                # a log file that possibly MAY exist but keep going to fetch other
                # log files. Today, this is better achieved by adding
                # ignore_errors or failed_when to the task.  Control the behaviour
                # via fail_when_missing
                if fail_on_missing:
                    result['failed'] = True
                    del result['changed']
                else:
                    result['msg'] += ", not transferring, ignored"
                return result

            # calculate checksum for the local file
            local_checksum = checksum(dest)

            if remote_checksum != local_checksum:
                # create the containing directories, if needed
                makedirs_safe(os.path.dirname(dest))

                # fetch the file and check for changes
                if remote_data is None:
                    self._connection.fetch_file(source, dest)
                else:
                    try:
                        f = open(to_bytes(dest, errors='surrogate_or_strict'), 'wb')
                        f.write(remote_data)
                        f.close()
                    except (IOError, OSError) as e:
                        raise AnsibleError("Failed to fetch the file: %s" % e)
                new_checksum = secure_hash(dest)
                # For backwards compatibility. We'll return None on FIPS enabled systems
                try:
                    new_md5 = md5(dest)
                except ValueError:
                    new_md5 = None

                if validate_checksum and new_checksum != remote_checksum:
                    result.update(dict(failed=True, md5sum=new_md5,
                                       msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None,
                                       checksum=new_checksum, remote_checksum=remote_checksum))
                else:
                    result.update({'changed': True, 'md5sum': new_md5, 'dest': dest,
                                   'remote_md5sum': None, 'checksum': new_checksum,
                                   'remote_checksum': remote_checksum})
            else:
                # For backwards compatibility. We'll return None on FIPS enabled systems
                try:
                    local_md5 = md5(dest)
                except ValueError:
                    local_md5 = None
                result.update(dict(changed=False, md5sum=local_md5, file=source, dest=dest, checksum=local_checksum))

        finally:
            self._remove_tmp_path(self._connection._shell.tmpdir)

        return result
コード例 #4
0
ファイル: fetch.py プロジェクト: vkvns/ansible
    def run(self, tmp=None, task_vars=None):
        ''' handler for fetch operations '''
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        if self._play_context.check_mode:
            result['skipped'] = True
            result['msg'] = 'check mode not (yet) supported for this module'
            return result

        source = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        flat = boolean(self._task.args.get('flat'))
        fail_on_missing = boolean(self._task.args.get('fail_on_missing'))
        validate_checksum = boolean(
            self._task.args.get('validate_checksum',
                                self._task.args.get('validate_md5')))

        if 'validate_md5' in self._task.args and 'validate_checksum' in self._task.args:
            result['failed'] = True
            result[
                'msg'] = "validate_checksum and validate_md5 cannot both be specified"
            return result

        if source is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
            return result

        source = self._connection._shell.join_path(source)
        source = self._remote_expand_user(source)

        remote_checksum = None
        if not self._play_context.become:
            # calculate checksum for the remote file, don't bother if using become as slurp will be used
            # Force remote_checksum to follow symlinks because fetch always follows symlinks
            remote_checksum = self._remote_checksum(source,
                                                    all_vars=task_vars,
                                                    follow=True)

        # use slurp if permissions are lacking or privilege escalation is needed
        remote_data = None
        if remote_checksum in ('1', '2', None):
            slurpres = self._execute_module(module_name='slurp',
                                            module_args=dict(src=source),
                                            task_vars=task_vars,
                                            tmp=tmp)
            if slurpres.get('failed'):
                if not fail_on_missing and (
                        slurpres.get('msg').startswith('file not found')
                        or remote_checksum == '1'):
                    result[
                        'msg'] = "the remote file does not exist, not transferring, ignored"
                    result['file'] = source
                    result['changed'] = False
                else:
                    result.update(slurpres)
                return result
            else:
                if slurpres['encoding'] == 'base64':
                    remote_data = base64.b64decode(slurpres['content'])
                if remote_data is not None:
                    remote_checksum = checksum_s(remote_data)
                # the source path may have been expanded on the
                # target system, so we compare it here and use the
                # expanded version if it's different
                remote_source = slurpres.get('source')
                if remote_source and remote_source != source:
                    source = remote_source

        # calculate the destination name
        if os.path.sep not in self._connection._shell.join_path('a', ''):
            source = self._connection._shell._unquote(source)
            source_local = source.replace('\\', '/')
        else:
            source_local = source

        dest = os.path.expanduser(dest)
        if flat:
            if dest.endswith(os.sep):
                # if the path ends with "/", we'll use the source filename as the
                # destination filename
                base = os.path.basename(source_local)
                dest = os.path.join(dest, base)
            if not dest.startswith("/"):
                # if dest does not start with "/", we'll assume a relative path
                dest = self._loader.path_dwim(dest)
        else:
            # files are saved in dest dir, with a subdir for each host, then the filename
            if 'inventory_hostname' in task_vars:
                target_name = task_vars['inventory_hostname']
            else:
                target_name = self._play_context.remote_addr
            dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name,
                                 source_local)

        dest = dest.replace("//", "/")

        if remote_checksum in ('0', '1', '2', '3', '4'):
            # these don't fail because you may want to transfer a log file that
            # possibly MAY exist but keep going to fetch other log files
            if remote_checksum == '0':
                result[
                    'msg'] = "unable to calculate the checksum of the remote file"
                result['file'] = source
                result['changed'] = False
            elif remote_checksum == '1':
                if fail_on_missing:
                    result['failed'] = True
                    result['msg'] = "the remote file does not exist"
                    result['file'] = source
                else:
                    result[
                        'msg'] = "the remote file does not exist, not transferring, ignored"
                    result['file'] = source
                    result['changed'] = False
            elif remote_checksum == '2':
                result[
                    'msg'] = "no read permission on remote file, not transferring, ignored"
                result['file'] = source
                result['changed'] = False
            elif remote_checksum == '3':
                result[
                    'msg'] = "remote file is a directory, fetch cannot work on directories"
                result['file'] = source
                result['changed'] = False
            elif remote_checksum == '4':
                result[
                    'msg'] = "python isn't present on the system.  Unable to compute checksum"
                result['file'] = source
                result['changed'] = False
            return result

        # calculate checksum for the local file
        local_checksum = checksum(dest)

        if remote_checksum != local_checksum:
            # create the containing directories, if needed
            makedirs_safe(os.path.dirname(dest))

            # fetch the file and check for changes
            if remote_data is None:
                self._connection.fetch_file(source, dest)
            else:
                try:
                    f = open(to_bytes(dest, errors='strict'), 'w')
                    f.write(remote_data)
                    f.close()
                except (IOError, OSError) as e:
                    raise AnsibleError("Failed to fetch the file: %s" % e)
            new_checksum = secure_hash(dest)
            # For backwards compatibility. We'll return None on FIPS enabled systems
            try:
                new_md5 = md5(dest)
            except ValueError:
                new_md5 = None

            if validate_checksum and new_checksum != remote_checksum:
                result.update(
                    dict(failed=True,
                         md5sum=new_md5,
                         msg="checksum mismatch",
                         file=source,
                         dest=dest,
                         remote_md5sum=None,
                         checksum=new_checksum,
                         remote_checksum=remote_checksum))
            else:
                result.update(
                    dict(changed=True,
                         md5sum=new_md5,
                         dest=dest,
                         remote_md5sum=None,
                         checksum=new_checksum,
                         remote_checksum=remote_checksum))
        else:
            # For backwards compatibility. We'll return None on FIPS enabled systems
            try:
                local_md5 = md5(dest)
            except ValueError:
                local_md5 = None
            result.update(
                dict(changed=False,
                     md5sum=local_md5,
                     file=source,
                     dest=dest,
                     checksum=local_checksum))

        return result
コード例 #5
0
ファイル: template.py プロジェクト: victron/paramiko_ssh-i
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for template operations '''

        source = self._task.args.get('src', None)
        dest   = self._task.args.get('dest', None)

        if (source is None and 'first_available_file' not in task_vars) or dest is None:
            return dict(failed=True, msg="src and dest are required")

        if tmp is None:
            tmp = self._make_tmp_path()

        ##################################################################################################
        # FIXME: this all needs to be sorted out
        ##################################################################################################
        # if we have first_available_file in our vars
        # look up the files and use the first one we find as src
        #if 'first_available_file' in task_vars:
        #    found = False
        #    for fn in task_vars.get('first_available_file'):
        #        fn_orig = fn
        #        fnt = template.template(self.runner.basedir, fn, task_vars)
        #        fnd = utils.path_dwim(self.runner.basedir, fnt)
        #        if not os.path.exists(fnd) and '_original_file' in task_vars:
        #            fnd = utils.path_dwim_relative(task_vars['_original_file'], 'templates', fnt, self.runner.basedir, check=False)
        #        if os.path.exists(fnd):
        #            source = fnd
        #            found = True
        #            break
        #    if not found:
        #        result = dict(failed=True, msg="could not find src in first_available_file list")
        #        return ReturnData(conn=conn, comm_ok=False, result=result)
        #else:
        if 1:
            if self._task._role is not None:
                source = self._loader.path_dwim_relative(self._task._role._role_path, 'templates', source)
            else:
                source = self._loader.path_dwim(source)
        ##################################################################################################
        # END FIXME
        ##################################################################################################

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest, tmp)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        templar = Templar(loader=self._loader, variables=task_vars)
        try:
            with open(source, 'r') as f:
                template_data = f.read()
            resultant = templar.template(template_data, preserve_trailing_newlines=True)
        except Exception as e:
            return dict(failed=True, msg=type(e).__name__ + ": " + str(e))

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(tmp, dest, not directory_prepended, source=source)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            return remote_checksum

        if local_checksum != remote_checksum:
            # if showing diffs, we need to get the remote value
            dest_contents = ''

            # FIXME: still need to implement diff mechanism
            #if self.runner.diff:
            #    # using persist_files to keep the temp directory around to avoid needing to grab another
            #    dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, task_vars=task_vars, persist_files=True)
            #    if 'content' in dest_result.result:
            #        dest_contents = dest_result.result['content']
            #        if dest_result.result['encoding'] == 'base64':
            #            dest_contents = base64.b64decode(dest_contents)
            #        else:
            #            raise Exception("unknown encoding, failed: %s" % dest_result.result)
 
            xfered = self._transfer_data(self._shell.join_path(tmp, 'source'), resultant)

            # fix file permissions when the copy is done as a different user
            if self._connection_info.become and self._connection_info.become_user != 'root':
                self._remote_chmod('a+r', xfered, tmp)

            # run the copy module
            new_module_args = self._task.args.copy()
            new_module_args.update(
               dict(
                   src=xfered,
                   dest=dest,
                   original_basename=os.path.basename(source),
                   follow=True,
                ),
            )

            # FIXME: noop stuff needs to be sorted out
            #if self.runner.noop_on_check(task_vars):
            #    return ReturnData(conn=conn, comm_ok=True, result=dict(changed=True), diff=dict(before_header=dest, after_header=source, before=dest_contents, after=resultant))
            #else:
            #    res = self.runner._execute_module(conn, tmp, 'copy', module_args_tmp, task_vars=task_vars, complex_args=complex_args)
            #    if res.result.get('changed', False):
            #        res.diff = dict(before=dest_contents, after=resultant)
            #    return res

            result = self._execute_module(module_name='copy', module_args=new_module_args)
            if result.get('changed', False):
                result['diff'] = dict(before=dest_contents, after=resultant)
            return result

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ),
            )

            # FIXME: this may not be required anymore, as the checkmod params
            #        should be in the regular module args?
            # be sure to task_vars the check mode param into the module args and
            # rely on the file module to report its changed status
            #if self.runner.noop_on_check(task_vars):
            #    new_module_args['CHECKMODE'] = True

            return self._execute_module(module_name='file', module_args=new_module_args)
コード例 #6
0
ファイル: fetch.py プロジェクト: ferhaty/ansible
    def run(self, tmp=None, task_vars=dict()):
        """ handler for fetch operations """

        if self._connection_info.check_mode:
            return dict(skipped=True, msg="check mode not (yet) supported for this module")

        source = self._task.args.get("src", None)
        dest = self._task.args.get("dest", None)
        flat = boolean(self._task.args.get("flat"))
        fail_on_missing = boolean(self._task.args.get("fail_on_missing"))
        validate_checksum = boolean(self._task.args.get("validate_checksum", self._task.args.get("validate_md5")))

        if "validate_md5" in self._task.args and "validate_checksum" in self._task.args:
            return dict(failed=True, msg="validate_checksum and validate_md5 cannot both be specified")

        if source is None or dest is None:
            return dict(failed=True, msg="src and dest are required")

        source = self._connection._shell.join_path(source)
        source = self._remote_expand_user(source, tmp)

        # calculate checksum for the remote file
        remote_checksum = self._remote_checksum(tmp, source)

        # use slurp if sudo and permissions are lacking
        remote_data = None
        if remote_checksum in ("1", "2") or self._connection_info.become:
            slurpres = self._execute_module(
                module_name="slurp", module_args=dict(src=source), task_vars=task_vars, tmp=tmp
            )
            if slurpres.get("rc") == 0:
                if slurpres["encoding"] == "base64":
                    remote_data = base64.b64decode(slurpres["content"])
                if remote_data is not None:
                    remote_checksum = checksum_s(remote_data)
                # the source path may have been expanded on the
                # target system, so we compare it here and use the
                # expanded version if it's different
                remote_source = slurpres.get("source")
                if remote_source and remote_source != source:
                    source = remote_source
            else:
                # FIXME: should raise an error here? the old code did nothing
                pass

        # calculate the destination name
        if os.path.sep not in self._connection._shell.join_path("a", ""):
            source_local = source.replace("\\", "/")
        else:
            source_local = source

        dest = os.path.expanduser(dest)
        if flat:
            if dest.endswith(os.sep):
                # if the path ends with "/", we'll use the source filename as the
                # destination filename
                base = os.path.basename(source_local)
                dest = os.path.join(dest, base)
            if not dest.startswith("/"):
                # if dest does not start with "/", we'll assume a relative path
                dest = self._loader.path_dwim(dest)
        else:
            # files are saved in dest dir, with a subdir for each host, then the filename
            if "inventory_hostname" in task_vars:
                target_name = task_vars["inventory_hostname"]
            else:
                target_name = self._connection_info.remote_addr
            dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name, source_local)

        dest = dest.replace("//", "/")

        if remote_checksum in ("0", "1", "2", "3", "4"):
            # these don't fail because you may want to transfer a log file that possibly MAY exist
            # but keep going to fetch other log files
            if remote_checksum == "0":
                result = dict(msg="unable to calculate the checksum of the remote file", file=source, changed=False)
            elif remote_checksum == "1":
                if fail_on_missing:
                    result = dict(failed=True, msg="the remote file does not exist", file=source)
                else:
                    result = dict(
                        msg="the remote file does not exist, not transferring, ignored", file=source, changed=False
                    )
            elif remote_checksum == "2":
                result = dict(
                    msg="no read permission on remote file, not transferring, ignored", file=source, changed=False
                )
            elif remote_checksum == "3":
                result = dict(
                    msg="remote file is a directory, fetch cannot work on directories", file=source, changed=False
                )
            elif remote_checksum == "4":
                result = dict(
                    msg="python isn't present on the system.  Unable to compute checksum", file=source, changed=False
                )
            return result

        # calculate checksum for the local file
        local_checksum = checksum(dest)

        if remote_checksum != local_checksum:
            # create the containing directories, if needed
            makedirs_safe(os.path.dirname(dest))

            # fetch the file and check for changes
            if remote_data is None:
                self._connection.fetch_file(source, dest)
            else:
                f = open(dest, "w")
                f.write(remote_data)
                f.close()
            new_checksum = secure_hash(dest)
            # For backwards compatibility.  We'll return None on FIPS enabled
            # systems
            try:
                new_md5 = md5(dest)
            except ValueError:
                new_md5 = None

            if validate_checksum and new_checksum != remote_checksum:
                return dict(
                    failed=True,
                    md5sum=new_md5,
                    msg="checksum mismatch",
                    file=source,
                    dest=dest,
                    remote_md5sum=None,
                    checksum=new_checksum,
                    remote_checksum=remote_checksum,
                )
            return dict(
                changed=True,
                md5sum=new_md5,
                dest=dest,
                remote_md5sum=None,
                checksum=new_checksum,
                remote_checksum=remote_checksum,
            )
        else:
            # For backwards compatibility.  We'll return None on FIPS enabled
            # systems
            try:
                local_md5 = md5(dest)
            except ValueError:
                local_md5 = None

            return dict(changed=False, md5sum=local_md5, file=source, dest=dest, checksum=local_checksum)
コード例 #7
0
ファイル: fetch.py プロジェクト: KMK-ONLINE/ansible
    def run(self, tmp=None, task_vars=None):
        ''' handler for fetch operations '''
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        if self._play_context.check_mode:
            result['skipped'] = True
            result['msg'] = 'check mode not (yet) supported for this module'
            return result

        source            = self._task.args.get('src', None)
        dest              = self._task.args.get('dest', None)
        flat              = boolean(self._task.args.get('flat'))
        fail_on_missing   = boolean(self._task.args.get('fail_on_missing'))
        validate_checksum = boolean(self._task.args.get('validate_checksum', self._task.args.get('validate_md5')))

        if 'validate_md5' in self._task.args and 'validate_checksum' in self._task.args:
            result['failed'] = True
            result['msg'] = "validate_checksum and validate_md5 cannot both be specified"
            return result

        if source is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
            return result

        source = self._connection._shell.join_path(source)
        source = self._remote_expand_user(source)

        remote_checksum = None
        if not self._play_context.become:
            # calculate checksum for the remote file, don't bother if using become as slurp will be used
            remote_checksum = self._remote_checksum(source, all_vars=task_vars)

        # use slurp if permissions are lacking or privilege escalation is needed
        remote_data = None
        if remote_checksum in ('1', '2', None):
            slurpres = self._execute_module(module_name='slurp', module_args=dict(src=source), task_vars=task_vars, tmp=tmp)
            if slurpres.get('failed'):
                if not fail_on_missing and (slurpres.get('msg').startswith('file not found') or remote_checksum == '1'):
                    result['msg'] = "the remote file does not exist, not transferring, ignored"
                    result['file'] = source
                    result['changed'] = False
                else:
                    result.update(slurpres)
                return result
            else:
                if slurpres['encoding'] == 'base64':
                    remote_data = base64.b64decode(slurpres['content'])
                if remote_data is not None:
                    remote_checksum = checksum_s(remote_data)
                # the source path may have been expanded on the
                # target system, so we compare it here and use the
                # expanded version if it's different
                remote_source = slurpres.get('source')
                if remote_source and remote_source != source:
                    source = remote_source

        # calculate the destination name
        if os.path.sep not in self._connection._shell.join_path('a', ''):
            source = self._connection._shell._unquote(source)
            source_local = source.replace('\\', '/')
        else:
            source_local = source

        dest = os.path.expanduser(dest)
        if flat:
            if dest.endswith(os.sep):
                # if the path ends with "/", we'll use the source filename as the
                # destination filename
                base = os.path.basename(source_local)
                dest = os.path.join(dest, base)
            if not dest.startswith("/"):
                # if dest does not start with "/", we'll assume a relative path
                dest = self._loader.path_dwim(dest)
        else:
            # files are saved in dest dir, with a subdir for each host, then the filename
            if 'inventory_hostname' in task_vars:
                target_name = task_vars['inventory_hostname']
            else:
                target_name = self._play_context.remote_addr
            dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name, source_local)

        dest = dest.replace("//","/")

        if remote_checksum in ('0', '1', '2', '3', '4'):
            # these don't fail because you may want to transfer a log file that
            # possibly MAY exist but keep going to fetch other log files
            if remote_checksum == '0':
                result['msg'] = "unable to calculate the checksum of the remote file"
                result['file'] = source
                result['changed'] = False
            elif remote_checksum == '1':
                if fail_on_missing:
                    result['failed'] = True
                    result['msg'] = "the remote file does not exist"
                    result['file'] = source
                else:
                    result['msg'] = "the remote file does not exist, not transferring, ignored"
                    result['file'] = source
                    result['changed'] = False
            elif remote_checksum == '2':
                result['msg'] = "no read permission on remote file, not transferring, ignored"
                result['file'] = source
                result['changed'] = False
            elif remote_checksum == '3':
                result['msg'] = "remote file is a directory, fetch cannot work on directories"
                result['file'] = source
                result['changed'] = False
            elif remote_checksum == '4':
                result['msg'] = "python isn't present on the system.  Unable to compute checksum"
                result['file'] = source
                result['changed'] = False
            return result

        # calculate checksum for the local file
        local_checksum = checksum(dest)

        if remote_checksum != local_checksum:
            # create the containing directories, if needed
            makedirs_safe(os.path.dirname(dest))

            # fetch the file and check for changes
            if remote_data is None:
                self._connection.fetch_file(source, dest)
            else:
                try:
                    f = open(to_bytes(dest, errors='strict'), 'w')
                    f.write(remote_data)
                    f.close()
                except (IOError, OSError) as e:
                    raise AnsibleError("Failed to fetch the file: %s" % e)
            new_checksum = secure_hash(dest)
            # For backwards compatibility. We'll return None on FIPS enabled systems
            try:
                new_md5 = md5(dest)
            except ValueError:
                new_md5 = None

            if validate_checksum and new_checksum != remote_checksum:
                result.update(dict(failed=True, md5sum=new_md5,
                    msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None,
                    checksum=new_checksum, remote_checksum=remote_checksum))
            else:
                result.update(dict(changed=True, md5sum=new_md5, dest=dest, remote_md5sum=None, checksum=new_checksum, remote_checksum=remote_checksum))
        else:
            # For backwards compatibility. We'll return None on FIPS enabled systems
            try:
                local_md5 = md5(dest)
            except ValueError:
                local_md5 = None
            result.update(dict(changed=False, md5sum=local_md5, file=source, dest=dest, checksum=local_checksum))

        return result
コード例 #8
0
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for fetch operations '''

        # FIXME: is this even required anymore?
        #if self.runner.noop_on_check(inject):
        #    return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not (yet) supported for this module'))

        source = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        flat = boolean(self._task.args.get('flat'))
        fail_on_missing = boolean(self._task.args.get('fail_on_missing'))
        validate_checksum = boolean(
            self._task.args.get('validate_checksum',
                                self._task.args.get('validate_md5')))

        if 'validate_md5' in self._task.args and 'validate_checksum' in self._task.args:
            return dict(
                failed=True,
                msg=
                "validate_checksum and validate_md5 cannot both be specified")

        if source is None or dest is None:
            return dict(failed=True, msg="src and dest are required")

        source = self._shell.join_path(source)
        source = self._remote_expand_user(source, tmp)

        # calculate checksum for the remote file
        remote_checksum = self._remote_checksum(tmp, source)

        # use slurp if sudo and permissions are lacking
        remote_data = None
        if remote_checksum in ('1', '2') or self._connection_info.become:
            slurpres = self._execute_module(module_name='slurp',
                                            module_args=dict(src=source),
                                            tmp=tmp)
            if slurpres.get('rc') == 0:
                if slurpres['encoding'] == 'base64':
                    remote_data = base64.b64decode(slurpres['content'])
                if remote_data is not None:
                    remote_checksum = checksum_s(remote_data)
                # the source path may have been expanded on the
                # target system, so we compare it here and use the
                # expanded version if it's different
                remote_source = slurpres.get('source')
                if remote_source and remote_source != source:
                    source = remote_source
            else:
                # FIXME: should raise an error here? the old code did nothing
                pass

        # calculate the destination name
        if os.path.sep not in self._shell.join_path('a', ''):
            source_local = source.replace('\\', '/')
        else:
            source_local = source

        dest = os.path.expanduser(dest)
        if flat:
            if dest.endswith("/"):
                # if the path ends with "/", we'll use the source filename as the
                # destination filename
                base = os.path.basename(source_local)
                dest = os.path.join(dest, base)
            if not dest.startswith("/"):
                # if dest does not start with "/", we'll assume a relative path
                dest = self._loader.path_dwim(dest)
        else:
            # files are saved in dest dir, with a subdir for each host, then the filename
            dest = "%s/%s/%s" % (self._loader.path_dwim(dest),
                                 self._connection_info.remote_addr,
                                 source_local)

        dest = dest.replace("//", "/")

        if remote_checksum in ('0', '1', '2', '3', '4'):
            # these don't fail because you may want to transfer a log file that possibly MAY exist
            # but keep going to fetch other log files
            if remote_checksum == '0':
                result = dict(
                    msg="unable to calculate the checksum of the remote file",
                    file=source,
                    changed=False)
            elif remote_checksum == '1':
                if fail_on_missing:
                    result = dict(failed=True,
                                  msg="the remote file does not exist",
                                  file=source)
                else:
                    result = dict(
                        msg=
                        "the remote file does not exist, not transferring, ignored",
                        file=source,
                        changed=False)
            elif remote_checksum == '2':
                result = dict(
                    msg=
                    "no read permission on remote file, not transferring, ignored",
                    file=source,
                    changed=False)
            elif remote_checksum == '3':
                result = dict(
                    msg=
                    "remote file is a directory, fetch cannot work on directories",
                    file=source,
                    changed=False)
            elif remote_checksum == '4':
                result = dict(
                    msg=
                    "python isn't present on the system.  Unable to compute checksum",
                    file=source,
                    changed=False)
            return result

        # calculate checksum for the local file
        local_checksum = checksum(dest)

        if remote_checksum != local_checksum:
            # create the containing directories, if needed
            if not os.path.isdir(os.path.dirname(dest)):
                os.makedirs(os.path.dirname(dest))

            # fetch the file and check for changes
            if remote_data is None:
                self._connection.fetch_file(source, dest)
            else:
                f = open(dest, 'w')
                f.write(remote_data)
                f.close()
            new_checksum = secure_hash(dest)
            # For backwards compatibility.  We'll return None on FIPS enabled
            # systems
            try:
                new_md5 = md5(dest)
            except ValueError:
                new_md5 = None

            if validate_checksum and new_checksum != remote_checksum:
                return dict(failed=True,
                            md5sum=new_md5,
                            msg="checksum mismatch",
                            file=source,
                            dest=dest,
                            remote_md5sum=None,
                            checksum=new_checksum,
                            remote_checksum=remote_checksum)
            return dict(changed=True,
                        md5sum=new_md5,
                        dest=dest,
                        remote_md5sum=None,
                        checksum=new_checksum,
                        remote_checksum=remote_checksum)
        else:
            # For backwards compatibility.  We'll return None on FIPS enabled
            # systems
            try:
                local_md5 = md5(dest)
            except ValueError:
                local_md5 = None

            return dict(changed=False,
                        md5sum=local_md5,
                        file=source,
                        dest=dest,
                        checksum=local_checksum)
コード例 #9
0
    def run(self, tmp=None, task_vars=None):
        ''' handler for fetch operations '''
        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 not (yet) supported for this module')

            source = self._task.args.get('src', None)
            original_dest = dest = self._task.args.get('dest', None)
            flat = boolean(self._task.args.get('flat'), strict=False)
            fail_on_missing = boolean(self._task.args.get(
                'fail_on_missing', True),
                                      strict=False)
            validate_checksum = boolean(self._task.args.get(
                'validate_checksum', True),
                                        strict=False)

            msg = ''
            # validate source and dest are strings FIXME: use basic.py and module specs
            if not isinstance(source, string_types):
                msg = "Invalid type supplied for source option, it must be a string"

            if not isinstance(dest, string_types):
                msg = "Invalid type supplied for dest option, it must be a string"

            if source is None or dest is None:
                msg = "src and dest are required"

            if msg:
                raise AnsibleActionFail(msg)

            source = self._connection._shell.join_path(source)
            source = self._remote_expand_user(source)

            remote_checksum = None
            if not self._connection.become:
                # calculate checksum for the remote file, don't bother if using become as slurp will be used
                # Force remote_checksum to follow symlinks because fetch always follows symlinks
                remote_checksum = self._remote_checksum(source,
                                                        all_vars=task_vars,
                                                        follow=True)

            # use slurp if permissions are lacking or privilege escalation is needed
            remote_data = None
            if remote_checksum in ('1', '2', None):
                slurpres = self._execute_module(
                    module_name='ansible.legacy.slurp',
                    module_args=dict(src=source),
                    task_vars=task_vars)
                if slurpres.get('failed'):
                    if not fail_on_missing and (
                            slurpres.get('msg').startswith('file not found')
                            or remote_checksum == '1'):
                        result[
                            'msg'] = "the remote file does not exist, not transferring, ignored"
                        result['file'] = source
                        result['changed'] = False
                    else:
                        result.update(slurpres)
                    return result
                else:
                    if slurpres['encoding'] == 'base64':
                        remote_data = base64.b64decode(slurpres['content'])
                    if remote_data is not None:
                        remote_checksum = checksum_s(remote_data)

            # calculate the destination name
            if os.path.sep not in self._connection._shell.join_path('a', ''):
                source = self._connection._shell._unquote(source)
                source_local = source.replace('\\', '/')
            else:
                source_local = source

            # ensure we only use file name, avoid relative paths
            if not is_subpath(dest, original_dest):
                # TODO: ? dest = os.path.expanduser(dest.replace(('../','')))
                raise AnsibleActionFail(
                    "Detected directory traversal, expected to be contained in '%s' but got '%s'"
                    % (original_dest, dest))

            if flat:
                if os.path.isdir(to_bytes(dest, errors='surrogate_or_strict')
                                 ) and not dest.endswith(os.sep):
                    raise AnsibleActionFail(
                        "dest is an existing directory, use a trailing slash if you want to fetch src into that directory"
                    )
                if dest.endswith(os.sep):
                    # if the path ends with "/", we'll use the source filename as the
                    # destination filename
                    base = os.path.basename(source_local)
                    dest = os.path.join(dest, base)
                if not dest.startswith("/"):
                    # if dest does not start with "/", we'll assume a relative path
                    dest = self._loader.path_dwim(dest)
            else:
                # files are saved in dest dir, with a subdir for each host, then the filename
                if 'inventory_hostname' in task_vars:
                    target_name = task_vars['inventory_hostname']
                else:
                    target_name = self._play_context.remote_addr
                dest = "%s/%s/%s" % (self._loader.path_dwim(dest), target_name,
                                     source_local)

            if remote_checksum in ('0', '1', '2', '3', '4', '5'):
                result['changed'] = False
                result['file'] = source
                if remote_checksum == '0':
                    result[
                        'msg'] = "unable to calculate the checksum of the remote file"
                elif remote_checksum == '1':
                    result['msg'] = "the remote file does not exist"
                elif remote_checksum == '2':
                    result['msg'] = "no read permission on remote file"
                elif remote_checksum == '3':
                    result[
                        'msg'] = "remote file is a directory, fetch cannot work on directories"
                elif remote_checksum == '4':
                    result[
                        'msg'] = "python isn't present on the system.  Unable to compute checksum"
                elif remote_checksum == '5':
                    result[
                        'msg'] = "stdlib json was not found on the remote machine. Only the raw module can work without those installed"
                # Historically, these don't fail because you may want to transfer
                # a log file that possibly MAY exist but keep going to fetch other
                # log files. Today, this is better achieved by adding
                # ignore_errors or failed_when to the task.  Control the behaviour
                # via fail_when_missing
                if fail_on_missing:
                    result['failed'] = True
                    del result['changed']
                else:
                    result['msg'] += ", not transferring, ignored"
                return result

            dest = os.path.normpath(dest)

            # calculate checksum for the local file
            local_checksum = checksum(dest)

            if remote_checksum != local_checksum:
                # create the containing directories, if needed
                makedirs_safe(os.path.dirname(dest))

                # fetch the file and check for changes
                if remote_data is None:
                    self._connection.fetch_file(source, dest)
                else:
                    try:
                        f = open(to_bytes(dest, errors='surrogate_or_strict'),
                                 'wb')
                        f.write(remote_data)
                        f.close()
                    except (IOError, OSError) as e:
                        raise AnsibleActionFail(
                            "Failed to fetch the file: %s" % e)
                new_checksum = secure_hash(dest)
                # For backwards compatibility. We'll return None on FIPS enabled systems
                try:
                    new_md5 = md5(dest)
                except ValueError:
                    new_md5 = None

                if validate_checksum and new_checksum != remote_checksum:
                    result.update(
                        dict(failed=True,
                             md5sum=new_md5,
                             msg="checksum mismatch",
                             file=source,
                             dest=dest,
                             remote_md5sum=None,
                             checksum=new_checksum,
                             remote_checksum=remote_checksum))
                else:
                    result.update({
                        'changed': True,
                        'md5sum': new_md5,
                        'dest': dest,
                        'remote_md5sum': None,
                        'checksum': new_checksum,
                        'remote_checksum': remote_checksum
                    })
            else:
                # For backwards compatibility. We'll return None on FIPS enabled systems
                try:
                    local_md5 = md5(dest)
                except ValueError:
                    local_md5 = None
                result.update(
                    dict(changed=False,
                         md5sum=local_md5,
                         file=source,
                         dest=dest,
                         checksum=local_checksum))

        finally:
            self._remove_tmp_path(self._connection._shell.tmpdir)

        return result
コード例 #10
0
ファイル: template.py プロジェクト: ferhaty/ansible
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for template operations '''

        source = self._task.args.get('src', None)
        dest   = self._task.args.get('dest', None)
        faf     = task_vars.get('first_available_file', None)

        if (source is None and faf is not None) or dest is None:
            return dict(failed=True, msg="src and dest are required")

        if tmp is None:
            tmp = self._make_tmp_path()

        if faf:
            #FIXME: issue deprecation warning for first_available_file, use with_first_found or lookup('first_found',...) instead
            found = False
            for fn in faf:
                fn_orig = fn
                fnt = self._templar.template(fn)
                fnd = self._loader.path_dwim(self._task._role_._role_path, 'templates', fnt)

                if not os.path.exists(fnd):
                    of = task_vars.get('_original_file', None)
                    if of is not None:
                        fnd = self._loader.path_dwim(self._task._role_._role_path, 'templates', of)

                if os.path.exists(fnd):
                    source = fnd
                    found = True
                    break
            if not found:
                return dict(failed=True, msg="could not find src in first_available_file list")
        else:
            if self._task._role is not None:
                source = self._loader.path_dwim_relative(self._task._role._role_path, 'templates', source)
            else:
                source = self._loader.path_dwim(source)

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest, tmp)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            with open(source, 'r') as f:
                template_data = f.read()
            resultant = self._templar.template(template_data, preserve_trailing_newlines=True)
        except Exception as e:
            return dict(failed=True, msg=type(e).__name__ + ": " + str(e))

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(tmp, dest, not directory_prepended, source=source)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            return remote_checksum

        if local_checksum != remote_checksum:
            # if showing diffs, we need to get the remote value
            dest_contents = ''

            # FIXME: still need to implement diff mechanism
            #if self.runner.diff:
            #    # using persist_files to keep the temp directory around to avoid needing to grab another
            #    dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, task_vars=task_vars, persist_files=True)
            #    if 'content' in dest_result.result:
            #        dest_contents = dest_result.result['content']
            #        if dest_result.result['encoding'] == 'base64':
            #            dest_contents = base64.b64decode(dest_contents)
            #        else:
            #            raise Exception("unknown encoding, failed: %s" % dest_result.result)

            xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)

            # fix file permissions when the copy is done as a different user
            if self._connection_info.become and self._connection_info.become_user != 'root':
                self._remote_chmod('a+r', xfered, tmp)

            # run the copy module
            new_module_args = self._task.args.copy()
            new_module_args.update(
               dict(
                   src=xfered,
                   dest=dest,
                   original_basename=os.path.basename(source),
                   follow=True,
                ),
            )

            result = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars)
            if result.get('changed', False):
                result['diff'] = dict(before=dest_contents, after=resultant)
            return result

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ),
            )

            return self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars)
コード例 #11
0
ファイル: template.py プロジェクト: wmedlar/ansible
    def run(self, tmp=None, task_vars=None):
        ''' handler for template operations '''

        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        source = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        force = boolean(self._task.args.get('force', True))
        state = self._task.args.get('state', None)
        newline_sequence = self._task.args.get('newline_sequence',
                                               self.DEFAULT_NEWLINE_SEQUENCE)
        variable_start_string = self._task.args.get('variable_start_string',
                                                    None)
        variable_end_string = self._task.args.get('variable_end_string', None)
        block_start_string = self._task.args.get('block_start_string', None)
        block_end_string = self._task.args.get('block_end_string', None)
        trim_blocks = self._task.args.get('trim_blocks', None)

        wrong_sequences = ["\\n", "\\r", "\\r\\n"]
        allowed_sequences = ["\n", "\r", "\r\n"]

        # We need to convert unescaped sequences to proper escaped sequences for Jinja2
        if newline_sequence in wrong_sequences:
            newline_sequence = allowed_sequences[wrong_sequences.index(
                newline_sequence)]

        if state is not None:
            result['failed'] = True
            result['msg'] = "'state' cannot be specified on a template"
        elif source is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
        elif newline_sequence not in allowed_sequences:
            result['failed'] = True
            result[
                'msg'] = "newline_sequence needs to be one of: \n, \r or \r\n"
        else:
            try:
                source = self._find_needle('templates', source)
            except AnsibleError as e:
                result['failed'] = True
                result['msg'] = to_text(e)

        if 'failed' in result:
            return result

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest)

        directory_prepended = False
        if dest.endswith(os.sep):
            # Optimization.  trailing slash means we know it's a directory
            directory_prepended = True
            dest = self._connection._shell.join_path(dest,
                                                     os.path.basename(source))
        else:
            # Find out if it's a directory
            dest_stat = self._execute_remote_stat(dest,
                                                  task_vars,
                                                  True,
                                                  tmp=tmp)
            if dest_stat['exists'] and dest_stat['isdir']:
                dest = self._connection._shell.join_path(
                    dest, os.path.basename(source))

        # Get vault decrypted tmp file
        try:
            tmp_source = self._loader.get_real_file(source)
        except AnsibleFileNotFound as e:
            result['failed'] = True
            result['msg'] = "could not find src=%s, %s" % (source, e)
            self._remove_tmp_path(tmp)
            return result

        # template the source data locally & get ready to transfer
        try:
            with open(tmp_source, 'r') as f:
                template_data = to_text(f.read())

            # set jinja2 internal search path for includes
            searchpath = task_vars.get('ansible_search_path', [])
            searchpath.extend([self._loader._basedir, os.path.dirname(source)])

            # We want to search into the 'templates' subdir of each search path in
            # addition to our original search paths.
            newsearchpath = []
            for p in searchpath:
                newsearchpath.append(os.path.join(p, 'templates'))
                newsearchpath.append(p)
            searchpath = newsearchpath

            self._templar.environment.loader.searchpath = searchpath
            self._templar.environment.newline_sequence = newline_sequence
            if block_start_string is not None:
                self._templar.environment.block_start_string = block_start_string
            if block_end_string is not None:
                self._templar.environment.block_end_string = block_end_string
            if variable_start_string is not None:
                self._templar.environment.variable_start_string = variable_start_string
            if variable_end_string is not None:
                self._templar.environment.variable_end_string = variable_end_string
            if trim_blocks is not None:
                self._templar.environment.trim_blocks = bool(trim_blocks)

            # add ansible 'template' vars
            temp_vars = task_vars.copy()
            temp_vars.update(generate_ansible_template_vars(source))

            old_vars = self._templar._available_variables
            self._templar.set_available_variables(temp_vars)
            resultant = self._templar.do_template(
                template_data,
                preserve_trailing_newlines=True,
                escape_backslashes=False)
            self._templar.set_available_variables(old_vars)
        except Exception as e:
            result['failed'] = True
            result['msg'] = "%s: %s" % (type(e).__name__, to_text(e))
            return result
        finally:
            self._loader.cleanup_tmp_file(tmp_source)

        if not tmp:
            tmp = self._make_tmp_path()

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(dest,
                                            task_vars,
                                            not directory_prepended,
                                            source=source,
                                            tmp=tmp)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            result.update(remote_checksum)
            return result

        diff = {}
        new_module_args = self._task.args.copy()

        # remove newline_sequence from standard arguments
        new_module_args.pop('newline_sequence', None)
        new_module_args.pop('block_start_string', None)
        new_module_args.pop('block_end_string', None)
        new_module_args.pop('variable_start_string', None)
        new_module_args.pop('variable_end_string', None)
        new_module_args.pop('trim_blocks', None)

        if (remote_checksum == '1') or (force
                                        and local_checksum != remote_checksum):

            result['changed'] = True
            # if showing diffs, we need to get the remote value
            if self._play_context.diff:
                diff = self._get_diff_data(dest,
                                           resultant,
                                           task_vars,
                                           source_file=False)

            if not self._play_context.check_mode:  # do actual work through copy
                xfered = self._transfer_data(
                    self._connection._shell.join_path(tmp, 'source'),
                    resultant)

                # fix file permissions when the copy is done as a different user
                self._fixup_perms2((tmp, xfered))

                # run the copy module
                new_module_args.update(
                    dict(
                        src=xfered,
                        dest=dest,
                        original_basename=os.path.basename(source),
                        follow=True,
                    ), )
                result.update(
                    self._execute_module(module_name='copy',
                                         module_args=new_module_args,
                                         task_vars=task_vars,
                                         tmp=tmp,
                                         delete_remote_tmp=False))

            if result.get('changed', False) and self._play_context.diff:
                result['diff'] = diff

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ), )
            result.update(
                self._execute_module(module_name='file',
                                     module_args=new_module_args,
                                     task_vars=task_vars,
                                     tmp=tmp,
                                     delete_remote_tmp=False))

        self._remove_tmp_path(tmp)

        return result
コード例 #12
0
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for template operations '''

        source = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        faf = self._task.first_available_file

        if (source is None and faf is not None) or dest is None:
            return dict(failed=True, msg="src and dest are required")

        if tmp is None:
            tmp = self._make_tmp_path()

        if faf:
            source = self._get_first_available_file(
                faf, task_vars.get('_original_file', None, 'templates'))
            if source is None:
                return dict(
                    failed=True,
                    msg="could not find src in first_available_file list")
        else:
            if self._task._role is not None:
                source = self._loader.path_dwim_relative(
                    self._task._role._role_path, 'templates', source)
            else:
                source = self._loader.path_dwim_relative(
                    self._loader.get_basedir(), 'templates', source)

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            with open(source, 'r') as f:
                template_data = to_unicode(f.read())

            try:
                template_uid = pwd.getpwuid(os.stat(source).st_uid).pw_name
            except:
                template_uid = os.stat(source).st_uid

            temp_vars = task_vars.copy()
            temp_vars['template_host'] = os.uname()[1]
            temp_vars['template_path'] = source
            temp_vars['template_mtime'] = datetime.datetime.fromtimestamp(
                os.path.getmtime(source))
            temp_vars['template_uid'] = template_uid
            temp_vars['template_fullpath'] = os.path.abspath(source)
            temp_vars['template_run_date'] = datetime.datetime.now()

            managed_default = C.DEFAULT_MANAGED_STR
            managed_str = managed_default.format(
                host=temp_vars['template_host'],
                uid=temp_vars['template_uid'],
                file=to_bytes(temp_vars['template_path']))
            temp_vars['ansible_managed'] = time.strftime(
                managed_str, time.localtime(os.path.getmtime(source)))

            # Create a new searchpath list to assign to the templar environment's file
            # loader, so that it knows about the other paths to find template files
            searchpath = [self._loader._basedir, os.path.dirname(source)]
            if self._task._role is not None:
                searchpath.insert(1, C.DEFAULT_ROLES_PATH)
                searchpath.insert(1, self._task._role._role_path)

            self._templar.environment.loader.searchpath = searchpath

            old_vars = self._templar._available_variables
            self._templar.set_available_variables(temp_vars)
            resultant = self._templar.template(template_data,
                                               preserve_trailing_newlines=True,
                                               escape_backslashes=False,
                                               convert_data=False)
            self._templar.set_available_variables(old_vars)
        except Exception as e:
            return dict(failed=True, msg=type(e).__name__ + ": " + str(e))

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(dest,
                                            task_vars,
                                            not directory_prepended,
                                            source=source)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            return remote_checksum

        diff = {}
        new_module_args = self._task.args.copy()

        if local_checksum != remote_checksum:
            dest_contents = ''

            # if showing diffs, we need to get the remote value
            if self._play_context.diff:
                diff = self._get_diff_data(dest,
                                           resultant,
                                           task_vars,
                                           source_file=False)

            if not self._play_context.check_mode:  # do actual work thorugh copy
                xfered = self._transfer_data(
                    self._connection._shell.join_path(tmp, 'source'),
                    resultant)

                # fix file permissions when the copy is done as a different user
                if self._play_context.become and self._play_context.become_user != 'root':
                    self._remote_chmod('a+r', xfered)

                # run the copy module
                new_module_args.update(
                    dict(
                        src=xfered,
                        dest=dest,
                        original_basename=os.path.basename(source),
                        follow=True,
                    ), )
                result = self._execute_module(module_name='copy',
                                              module_args=new_module_args,
                                              task_vars=task_vars)
            else:
                result = dict(changed=True)

            if result.get('changed', False) and self._play_context.diff:
                result['diff'] = diff
            #    result['diff'] = dict(before=dest_contents, after=resultant, before_header=dest, after_header=source)

            return result

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ), )

            return self._execute_module(module_name='file',
                                        module_args=new_module_args,
                                        task_vars=task_vars)
コード例 #13
0
    def run(self, tmp=None, task_vars=None):
        ''' handler for template operations '''
        if task_vars is None:
            task_vars = dict()

        res = self.create_aeriscloud_directory(tmp, task_vars)
        if 'failed' in res:
            return res

        result = super(ActionModule, self).run(tmp, task_vars)

        name = self._task.args.get('name', None)
        services = self._task.args.get('services', None)

        data = {
            'services': []
        }

        for service in services:
            if 'when' in service and not self._task.evaluate_conditional(service['when'], task_vars):
                continue
            if 'path' in service and 'protocol' not in service:
                service['protocol'] = 'http'
            if 'path' not in service:
                service['path'] = ''
            if 'protocol' not in service:
                service['protocol'] = 'tcp'
            data['services'].append(service)

        template = jinja2.Template("""{%- for service in services -%}
{{ service['name'] }},{{ service['port'] }},{{ service['path'] }},{{ service['protocol'] }}
{% endfor %}""")

        resultant = template.render(data)

        # Expand any user home dir specification
        dest = self._remote_expand_user(os.path.join('/etc/aeriscloud.d', name))
        directory_prepended = True

        remote_user = task_vars.get('ansible_ssh_user') or self._play_context.remote_user
        if not tmp:
            tmp = self._make_tmp_path(remote_user)
            self._cleanup_remote_tmp = True

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(dest, task_vars, not directory_prepended, source=dest, tmp=tmp)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            result.update(remote_checksum)
            return result

        diff = {}
        new_module_args = {
            'mode': 0644,
            'owner': 'root',
            'group': 'root'
        }

        if (remote_checksum == '1') or (local_checksum != remote_checksum):

            result['changed'] = True
            # if showing diffs, we need to get the remote value
            if self._play_context.diff:
                diff = self._get_diff_data(dest, resultant, task_vars, source_file=False)

            if not self._play_context.check_mode:  # do actual work through copy
                xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)

                # fix file permissions when the copy is done as a different user
                self._fixup_perms(xfered, remote_user)

                # run the copy module
                new_module_args.update(
                    dict(
                        src=xfered,
                        dest=dest,
                        original_basename=os.path.basename(dest),
                        follow=True,
                    ),
                )
                result.update(self._execute_module(
                    module_name='copy',
                    module_args=new_module_args,
                    task_vars=task_vars,
                    tmp=tmp,
                    delete_remote_tmp=False))

            if result.get('changed', False) and self._play_context.diff:
                result['diff'] = diff

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args.update(
                dict(
                    path=dest,
                    src=None,
                    original_basename=os.path.basename(dest),
                    follow=True,
                ),
            )
            result.update(self._execute_module(
                module_name='file',
                module_args=new_module_args,
                task_vars=task_vars,
                tmp=tmp,
                delete_remote_tmp=False))

        self._remove_tmp_path(tmp)

        return result
コード例 #14
0
    def run(self, tmp=None, task_vars=None):

        self._supports_check_mode = False

        result = super(ActionModule, self).run(tmp, task_vars)
        del tmp  # tmp no longer has any effect

        if task_vars is None:
            task_vars = dict()

        src = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        delimiter = self._task.args.get('delimiter', None)
        remote_src = self._task.args.get('remote_src', 'yes')
        regexp = self._task.args.get('regexp', None)
        follow = self._task.args.get('follow', False)
        ignore_hidden = self._task.args.get('ignore_hidden', False)
        decrypt = self._task.args.get('decrypt', True)

        try:
            if src is None or dest is None:
                raise AnsibleActionFail("src and dest are required")

            if boolean(remote_src, strict=False):
                result.update(
                    self._execute_module(module_name='assemble',
                                         task_vars=task_vars))
                raise _AnsibleActionDone()
            else:
                try:
                    src = self._find_needle('files', src)
                except AnsibleError as e:
                    raise AnsibleActionFail(to_native(e))

            if not os.path.isdir(src):
                raise AnsibleActionFail(u"Source (%s) is not a directory" %
                                        src)

            _re = None
            if regexp is not None:
                _re = re.compile(regexp)

            # Does all work assembling the file
            path = self._assemble_from_fragments(src, delimiter, _re,
                                                 ignore_hidden, decrypt)

            path_checksum = checksum_s(path)
            dest = self._remote_expand_user(dest)
            dest_stat = self._execute_remote_stat(dest,
                                                  all_vars=task_vars,
                                                  follow=follow)

            diff = {}

            # setup args for running modules
            new_module_args = self._task.args.copy()

            # clean assemble specific options
            for opt in [
                    'remote_src', 'regexp', 'delimiter', 'ignore_hidden',
                    'decrypt'
            ]:
                if opt in new_module_args:
                    del new_module_args[opt]
            new_module_args['dest'] = dest

            if path_checksum != dest_stat['checksum']:

                if self._play_context.diff:
                    diff = self._get_diff_data(dest, path, task_vars)

                remote_path = self._connection._shell.join_path(
                    self._connection._shell.tmpdir, 'src')
                xfered = self._transfer_file(path, remote_path)

                # fix file permissions when the copy is done as a different user
                self._fixup_perms2(
                    (self._connection._shell.tmpdir, remote_path))

                new_module_args.update(dict(src=xfered, ))

                res = self._execute_module(module_name='copy',
                                           module_args=new_module_args,
                                           task_vars=task_vars)
                if diff:
                    res['diff'] = diff
                result.update(res)
            else:
                result.update(
                    self._execute_module(module_name='file',
                                         module_args=new_module_args,
                                         task_vars=task_vars))

        except AnsibleAction as e:
            result.update(e.result)
        finally:
            self._remove_tmp_path(self._connection._shell.tmpdir)

        return result
コード例 #15
0
ファイル: assemble.py プロジェクト: victron/paramiko_ssh-i
    def run(self, tmp=None, task_vars=dict()):

        src        = self._task.args.get('src', None)
        dest       = self._task.args.get('dest', None)
        delimiter  = self._task.args.get('delimiter', None)
        remote_src = self._task.args.get('remote_src', 'yes')
        regexp     = self._task.args.get('regexp', None)

        if src is None or dest is None:
            return dict(failed=True, msg="src and dest are required")

        if boolean(remote_src):
            return self._execute_module(tmp=tmp)
        elif self._task._role is not None:
            src = self._loader.path_dwim_relative(self._task._role._role_path, 'files', src)
        else:
            # the source is local, so expand it here
            src = self._loader.path_dwim(os.path.expanduser(src))

        _re = None
        if regexp is not None:
            _re = re.compile(regexp)

        # Does all work assembling the file
        path = self._assemble_from_fragments(src, delimiter, _re)

        path_checksum = checksum_s(path)
        dest = self._remote_expand_user(dest, tmp)
        remote_checksum = self._remote_checksum(tmp, dest)

        if path_checksum != remote_checksum:
            resultant = file(path).read()
            # FIXME: diff needs to be moved somewhere else
            #if self.runner.diff:
            #    dest_result = self._execute_module(module_name='slurp', module_args=dict(path=dest), tmp=tmp, persist_files=True)
            #    if 'content' in dest_result:
            #        dest_contents = dest_result['content']
            #        if dest_result['encoding'] == 'base64':
            #            dest_contents = base64.b64decode(dest_contents)
            #        else:
            #            raise Exception("unknown encoding, failed: %s" % dest_result)
            xfered = self._transfer_data('src', resultant)

            # fix file permissions when the copy is done as a different user
            if self._connection_info.become and self._connection_info.become_user != 'root':
                self._remote_chmod('a+r', xfered, tmp)

            # run the copy module
            
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=xfered,
                    dest=dest,
                    original_basename=os.path.basename(src),
                )
            )

            # FIXME: checkmode stuff
            #if self.runner.noop_on_check(inject):
            #    return ReturnData(conn=conn, comm_ok=True, result=dict(changed=True), diff=dict(before_header=dest, after_header=src, after=resultant))
            #else:
            #    res = self.runner._execute_module(conn, tmp, 'copy', module_args_tmp, inject=inject)
            #    res.diff = dict(after=resultant)
            #    return res
            res = self._execute_module(module_name='copy', module_args=new_module_args, tmp=tmp)
            #res.diff = dict(after=resultant)
            return res
        else:
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=xfered,
                    dest=dest,
                    original_basename=os.path.basename(src),
                )
            )

            return self._execute_module(module_name='file', module_args=new_module_args, tmp=tmp)
コード例 #16
0
    def run(self, tmp=None, task_vars=None):
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        if self._play_context.check_mode:
            result['skipped'] = True
            result['msg'] = "skipped, this module does not support check_mode."
            return result

        src        = self._task.args.get('src', None)
        dest       = self._task.args.get('dest', None)
        delimiter  = self._task.args.get('delimiter', None)
        remote_src = self._task.args.get('remote_src', 'yes')
        regexp     = self._task.args.get('regexp', None)
        follow     = self._task.args.get('follow', False)
        ignore_hidden = self._task.args.get('ignore_hidden', False)

        if src is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
            return result

        remote_user = task_vars.get('ansible_ssh_user') or self._play_context.remote_user
        if not tmp:
            tmp = self._make_tmp_path(remote_user)
            self._cleanup_remote_tmp = True

        if boolean(remote_src):
            result.update(self._execute_module(tmp=tmp, task_vars=task_vars, delete_remote_tmp=False))
            self._remove_tmp_path(tmp)
            return result
        else:
            try:
                src = self._find_needle('files', src)
            except AnsibleError as e:
                result['failed'] = True
                result['msg'] = to_str(e)
                return result

        if not os.path.isdir(src):
            result['failed'] = True
            result['msg'] = "Source (%s) is not a directory" % src
            return result

        _re = None
        if regexp is not None:
            _re = re.compile(regexp)

        # Does all work assembling the file
        path = self._assemble_from_fragments(src, delimiter, _re, ignore_hidden)

        path_checksum = checksum_s(path)
        dest = self._remote_expand_user(dest)
        dest_stat = self._execute_remote_stat(dest, all_vars=task_vars, follow=follow, tmp=tmp)

        diff = {}

        # setup args for running modules
        new_module_args = self._task.args.copy()

        # clean assemble specific options
        for opt in ['remote_src', 'regexp', 'delimiter', 'ignore_hidden']:
            if opt in new_module_args:
                del new_module_args[opt]

        new_module_args.update(
            dict(
                dest=dest,
                original_basename=os.path.basename(src),
            )
        )

        if path_checksum != dest_stat['checksum']:

            if self._play_context.diff:
                diff = self._get_diff_data(dest, path, task_vars)

            remote_path = self._connection._shell.join_path(tmp, 'src')
            xfered = self._transfer_file(path, remote_path)

            # fix file permissions when the copy is done as a different user
            self._fixup_perms((tmp, remote_path), remote_user)

            new_module_args.update( dict( src=xfered,))

            res = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False)
            if diff:
                res['diff'] = diff
            result.update(res)
        else:
            result.update(self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))

        self._remove_tmp_path(tmp)

        return result
コード例 #17
0
ファイル: jsonnet.py プロジェクト: mikedanese/ansible-jsonnet
    def run(self, tmp=None, task_vars=None):
        ''' handler for template operations '''
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        source = self._task.args.get('src', None)
        dest   = self._task.args.get('dest', None)
        faf    = self._task.first_available_file
        force  = boolean(self._task.args.get('force', True))
        state  = self._task.args.get('state', None)

        if state is not None:
            result['failed'] = True
            result['msg'] = "'state' cannot be specified on a template"
            return result
        elif (source is None and faf is not None) or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
            return result

        if faf:
            source = self._get_first_available_file(faf, task_vars.get('_original_file', None, 'templates'))
            if source is None:
                result['failed'] = True
                result['msg'] = "could not find src in first_available_file list"
                return result
        else:
            if self._task._role is not None:
                source = self._loader.path_dwim_relative(self._task._role._role_path, 'templates', source)
            else:
                source = self._loader.path_dwim_relative(self._loader.get_basedir(), 'templates', source)

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            with open(source, 'r') as f:
                template_data = to_unicode(f.read())

            temp_vars = task_vars.copy()
            if 'hostvars' in temp_vars['vars']:
              del temp_vars['vars']['hostvars']

            # Create a new searchpath list to assign to the templar environment's file
            # loader, so that it knows about the other paths to find template files
            searchpath = [self._loader._basedir, os.path.dirname(source)]
            if self._task._role is not None:
                if C.DEFAULT_ROLES_PATH:
                    searchpath[:0] = C.DEFAULT_ROLES_PATH
                searchpath.insert(1, self._task._role._role_path)

            resultant = _jsonnet.evaluate_snippet(
                source,
                template_data,
                tla_codes={'cfg': json.dumps(temp_vars['vars'])},
                import_callback=import_callback(searchpath),
            )
        except Exception as e:
            result['failed'] = True
            result['msg'] = type(e).__name__ + ": " + str(e)
            return result

        remote_user = task_vars.get('ansible_ssh_user') or self._play_context.remote_user
        if not tmp:
            tmp = self._make_tmp_path(remote_user)
            self._cleanup_remote_tmp = True

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(dest, task_vars, not directory_prepended, source=source, tmp=tmp)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            result.update(remote_checksum)
            return result

        diff = {}
        new_module_args = self._task.args.copy()

        if (remote_checksum == '1') or (force and local_checksum != remote_checksum):

            result['changed'] = True
            # if showing diffs, we need to get the remote value
            if self._play_context.diff:
                diff = self._get_diff_data(dest, resultant, task_vars, source_file=False)

            if not self._play_context.check_mode: # do actual work thorugh copy
                xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)

                # fix file permissions when the copy is done as a different user
                self._fixup_perms(tmp, remote_user, recursive=True)

                # run the copy module
                new_module_args.update(
                   dict(
                       src=xfered,
                       dest=dest,
                       original_basename=os.path.basename(source),
                       follow=True,
                    ),
                )
                result.update(self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))

            if result.get('changed', False) and self._play_context.diff:
                result['diff'] = diff

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ),
            )
            result.update(self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))

        self._remove_tmp_path(tmp)

        return result
コード例 #18
0
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for package operations '''
        dest  = self._task.args.get('dest', None)
        url   = self._task.args.get('src', None)
        method = self._task.args.get('method', 'GET')
        headers = self._task.args.get('headers', dict())

        uri_params = ['method', 'headers']


        if tmp is None:
            tmp = self._make_tmp_path()

        source = tmp + '/temp.j2'

        new_module_args = self._task.args.copy()
        new_module_args.update(
                dict(
                    url=url,
                    dest=source,
                    headers=headers,
                    method=method
                ),
            )
        result = self._execute_module(module_name='uri', module_args=new_module_args, task_vars=task_vars)



        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            with open(source, 'r') as f:
                template_data = to_unicode(f.read())

            try:
                template_uid = pwd.getpwuid(os.stat(source).st_uid).pw_name
            except:
                template_uid = os.stat(source).st_uid

            temp_vars = task_vars.copy()
            temp_vars['template_host']     = os.uname()[1]
            temp_vars['template_path']     = source
            temp_vars['template_mtime']    = datetime.datetime.fromtimestamp(os.path.getmtime(source))
            temp_vars['template_uid']      = template_uid
            temp_vars['template_fullpath'] = os.path.abspath(source)
            temp_vars['template_run_date'] = datetime.datetime.now()

            managed_default = C.DEFAULT_MANAGED_STR
            managed_str = managed_default.format(
                host = temp_vars['template_host'],
                uid  = temp_vars['template_uid'],
                file = to_bytes(temp_vars['template_path'])
            )
            temp_vars['ansible_managed'] = time.strftime(
                managed_str,
                time.localtime(os.path.getmtime(source))
            )

            old_vars = self._templar._available_variables
            self._templar.set_available_variables(temp_vars)
            resultant = self._templar.template(template_data, preserve_trailing_newlines=True, convert_data=False)
            self._templar.set_available_variables(old_vars)
        except Exception as e:
            return dict(failed=True, msg=type(e).__name__ + ": " + str(e))

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(tmp, dest, not directory_prepended, source=source)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            return remote_checksum

        if local_checksum != remote_checksum:
            # if showing diffs, we need to get the remote value
            dest_contents = ''

            xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)

            # fix file permissions when the copy is done as a different user
            if self._play_context.become and self._play_context.become_user != 'root':
                self._remote_chmod('a+r', xfered, tmp)

            # run the copy module
            new_module_args = self._task.args.copy()
            for param in uri_params:
                if param in new_module_args:
                    del new_module_args[param]
            new_module_args.update(
               dict(
                   src=xfered,
                   dest=dest,
                   original_basename=os.path.basename(source),
                   follow=True,
                ),
            )

            result = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars)
            if result.get('changed', False):
                result['diff'] = dict(before=dest_contents, after=resultant)
            return result

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args = self._task.args.copy()
            for param in uri_params:
                if param in new_module_args:
                    del new_module_args[param]
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ),
            )

            return self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars)
コード例 #19
0
    def run(self, tmp=None, task_vars=None):
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        if self._play_context.check_mode:
            result['skipped'] = True
            result['msg'] = "skipped, this module does not support check_mode."
            return result

        src        = self._task.args.get('src', None)
        dest       = self._task.args.get('dest', None)
        delimiter  = self._task.args.get('delimiter', None)
        remote_src = self._task.args.get('remote_src', 'yes')
        regexp     = self._task.args.get('regexp', None)
        follow     = self._task.args.get('follow', False)
        ignore_hidden = self._task.args.get('ignore_hidden', False)

        if src is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
            return result

        if boolean(remote_src):
            result.update(self._execute_module(tmp=tmp, task_vars=task_vars))
            return result

        elif self._task._role is not None:
            src = self._loader.path_dwim_relative(self._task._role._role_path, 'files', src)
        else:
            src = self._loader.path_dwim_relative(self._loader.get_basedir(), 'files', src)

        _re = None
        if regexp is not None:
            _re = re.compile(regexp)

        if not os.path.isdir(src):
            result['failed'] = True
            result['msg'] = "Source (%s) is not a directory" % src
            return result

        # Does all work assembling the file
        path = self._assemble_from_fragments(src, delimiter, _re, ignore_hidden)

        path_checksum = checksum_s(path)
        dest = self._remote_expand_user(dest)
        dest_stat = self._execute_remote_stat(dest, all_vars=task_vars, follow=follow)

        diff = {}
        if path_checksum != dest_stat['checksum']:
            resultant = file(path).read()

            if self._play_context.diff:
                diff = self._get_diff_data(dest, path, task_vars)

            xfered = self._transfer_data('src', resultant)

            # fix file permissions when the copy is done as a different user
            if self._play_context.become and self._play_context.become_user != 'root':
                self._remote_chmod('a+r', xfered)

            # run the copy module

            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=xfered,
                    dest=dest,
                    original_basename=os.path.basename(src),
                )
            )

            res = self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp)
            if diff:
                res['diff'] = diff
            result.update(res)
            return result
        else:
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=xfered,
                    dest=dest,
                    original_basename=os.path.basename(src),
                )
            )

            result.update(self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, tmp=tmp))
            return result
コード例 #20
0
ファイル: fetch.py プロジェクト: dataxu/ansible
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for fetch operations '''

        # FIXME: is this even required anymore?
        #if self.runner.noop_on_check(inject):
        #    return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not (yet) supported for this module'))

        source            = self._task.args.get('src', None)
        dest              = self._task.args.get('dest', None)
        flat              = boolean(self._task.args.get('flat'))
        fail_on_missing   = boolean(self._task.args.get('fail_on_missing'))
        validate_checksum = boolean(self._task.args.get('validate_checksum', self._task.args.get('validate_md5')))

        if 'validate_md5' in self._task.args and 'validate_checksum' in self._task.args:
            return dict(failed=True, msg="validate_checksum and validate_md5 cannot both be specified")

        if source is None or dest is None:
            return dict(failed=True, msg="src and dest are required")

        source = self._shell.join_path(source)
        source = self._remote_expand_user(source, tmp)

        # calculate checksum for the remote file
        remote_checksum = self._remote_checksum(tmp, source)

        # use slurp if sudo and permissions are lacking
        remote_data = None
        if remote_checksum in ('1', '2') or self._connection_info.sudo:
            slurpres = self._execute_module(module_name='slurp', module_args=dict(src=source), tmp=tmp)
            if slurpres.get('rc') == 0:
                if slurpres['encoding'] == 'base64':
                    remote_data = base64.b64decode(slurpres['content'])
                if remote_data is not None:
                    remote_checksum = checksum_s(remote_data)
                # the source path may have been expanded on the
                # target system, so we compare it here and use the
                # expanded version if it's different
                remote_source = slurpres.get('source')
                if remote_source and remote_source != source:
                    source = remote_source
            else:
                # FIXME: should raise an error here? the old code did nothing
                pass

        # calculate the destination name
        if os.path.sep not in self._shell.join_path('a', ''):
            source_local = source.replace('\\', '/')
        else:
            source_local = source

        dest = os.path.expanduser(dest)
        if flat:
            if dest.endswith("/"):
                # if the path ends with "/", we'll use the source filename as the
                # destination filename
                base = os.path.basename(source_local)
                dest = os.path.join(dest, base)
            if not dest.startswith("/"):
                # if dest does not start with "/", we'll assume a relative path
                dest = self._loader.path_dwim(dest)
        else:
            # files are saved in dest dir, with a subdir for each host, then the filename
            dest = "%s/%s/%s" % (self._loader.path_dwim(dest), self._connection_info.remote_addr, source_local)

        dest = dest.replace("//","/")

        if remote_checksum in ('0', '1', '2', '3', '4'):
            # these don't fail because you may want to transfer a log file that possibly MAY exist
            # but keep going to fetch other log files
            if remote_checksum == '0':
                result = dict(msg="unable to calculate the checksum of the remote file", file=source, changed=False)
            elif remote_checksum == '1':
                if fail_on_missing:
                    result = dict(failed=True, msg="the remote file does not exist", file=source)
                else:
                    result = dict(msg="the remote file does not exist, not transferring, ignored", file=source, changed=False)
            elif remote_checksum == '2':
                result = dict(msg="no read permission on remote file, not transferring, ignored", file=source, changed=False)
            elif remote_checksum == '3':
                result = dict(msg="remote file is a directory, fetch cannot work on directories", file=source, changed=False)
            elif remote_checksum == '4':
                result = dict(msg="python isn't present on the system.  Unable to compute checksum", file=source, changed=False)
            return result

        # calculate checksum for the local file
        local_checksum = checksum(dest)

        if remote_checksum != local_checksum:
            # create the containing directories, if needed
            if not os.path.isdir(os.path.dirname(dest)):
                os.makedirs(os.path.dirname(dest))

            # fetch the file and check for changes
            if remote_data is None:
                self._connection.fetch_file(source, dest)
            else:
                f = open(dest, 'w')
                f.write(remote_data)
                f.close()
            new_checksum = secure_hash(dest)
            # For backwards compatibility.  We'll return None on FIPS enabled
            # systems
            try:
                new_md5 = md5(dest)
            except ValueError:
                new_md5 = None

            if validate_checksum and new_checksum != remote_checksum:
                return dict(failed=True, md5sum=new_md5, msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None, checksum=new_checksum, remote_checksum=remote_checksum)
            return dict(changed=True, md5sum=new_md5, dest=dest, remote_md5sum=None, checksum=new_checksum, remote_checksum=remote_checksum)
        else:
            # For backwards compatibility.  We'll return None on FIPS enabled
            # systems
            try:
                local_md5 = md5(dest)
            except ValueError:
                local_md5 = None

            return dict(changed=False, md5sum=local_md5, file=source, dest=dest, checksum=local_checksum)
コード例 #21
0
    def run(self, tmp=None, task_vars=None):
        ''' handler for template operations '''
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)

        source = self._task.args.get('src', None)
        dest   = self._task.args.get('dest', None)
        force  = boolean(self._task.args.get('force', True))
        state  = self._task.args.get('state', None)

        if state is not None:
            result['failed'] = True
            result['msg'] = "'state' cannot be specified on a template"
        elif source is None or dest is None:
            result['failed'] = True
            result['msg'] = "src and dest are required"
        else:
            try:
                source = self._find_needle('templates', source)
            except AnsibleError as e:
                result['failed'] = True
                result['msg'] = to_native(e)

        if 'failed' in result:
            return result

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        b_source = to_bytes(source)
        try:
            with open(b_source, 'r') as f:
                template_data = to_text(f.read())

            try:
                template_uid = pwd.getpwuid(os.stat(b_source).st_uid).pw_name
            except:
                template_uid = os.stat(b_source).st_uid

            temp_vars = task_vars.copy()
            temp_vars['template_host']     = os.uname()[1]
            temp_vars['template_path']     = source
            temp_vars['template_mtime']    = datetime.datetime.fromtimestamp(os.path.getmtime(b_source))
            temp_vars['template_uid']      = template_uid
            temp_vars['template_fullpath'] = os.path.abspath(source)
            temp_vars['template_run_date'] = datetime.datetime.now()

            managed_default = C.DEFAULT_MANAGED_STR
            managed_str = managed_default.format(
                host = temp_vars['template_host'],
                uid  = temp_vars['template_uid'],
                file = to_bytes(temp_vars['template_path'])
            )
            temp_vars['ansible_managed'] = time.strftime(
                managed_str,
                time.localtime(os.path.getmtime(b_source))
            )

            # Create a new searchpath list to assign to the templar environment's file
            # loader, so that it knows about the other paths to find template files
            searchpath = [self._loader._basedir, os.path.dirname(source)]
            if self._task._role is not None:
                if C.DEFAULT_ROLES_PATH:
                    searchpath[:0] = C.DEFAULT_ROLES_PATH
                searchpath.insert(1, self._task._role._role_path)

            self._templar.environment.loader.searchpath = searchpath

            old_vars = self._templar._available_variables
            self._templar.set_available_variables(temp_vars)
            resultant = self._templar.template(template_data, preserve_trailing_newlines=True, escape_backslashes=False, convert_data=False)
            self._templar.set_available_variables(old_vars)
        except Exception as e:
            result['failed'] = True
            result['msg'] = type(e).__name__ + ": " + str(e)
            return result

        remote_user = task_vars.get('ansible_ssh_user') or self._play_context.remote_user
        if not tmp:
            tmp = self._make_tmp_path(remote_user)
            self._cleanup_remote_tmp = True

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(dest, task_vars, not directory_prepended, source=source, tmp=tmp)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            result.update(remote_checksum)
            return result

        diff = {}
        new_module_args = self._task.args.copy()

        if (remote_checksum == '1') or (force and local_checksum != remote_checksum):

            result['changed'] = True
            # if showing diffs, we need to get the remote value
            if self._play_context.diff:
                diff = self._get_diff_data(dest, resultant, task_vars, source_file=False)

            if not self._play_context.check_mode:  # do actual work through copy
                xfered = self._transfer_data(self._connection._shell.join_path(tmp, 'source'), resultant)

                # fix file permissions when the copy is done as a different user
                self._fixup_perms2((tmp, xfered), remote_user)

                # run the copy module
                new_module_args.update(
                   dict(
                       src=xfered,
                       dest=dest,
                       original_basename=os.path.basename(source),
                       follow=True,
                   ),
                )
                result.update(self._execute_module(module_name='copy', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))

            if result.get('changed', False) and self._play_context.diff:
                result['diff'] = diff

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ),
            )
            result.update(self._execute_module(module_name='file', module_args=new_module_args, task_vars=task_vars, tmp=tmp, delete_remote_tmp=False))

        self._remove_tmp_path(tmp)

        return result
コード例 #22
0
ファイル: template.py プロジェクト: woltage/ansible
    def run(self, tmp=None, task_vars=dict()):
        ''' handler for template operations '''

        source = self._task.args.get('src', None)
        dest = self._task.args.get('dest', None)
        faf = self._task.first_available_file

        if (source is None and faf is not None) or dest is None:
            return dict(failed=True, msg="src and dest are required")

        if tmp is None:
            tmp = self._make_tmp_path()

        if faf:
            #FIXME: issue deprecation warning for first_available_file, use with_first_found or lookup('first_found',...) instead
            found = False
            for fn in faf:
                fn_orig = fn
                fnt = self._templar.template(fn)
                fnd = self._loader.path_dwim(self._task._role_._role_path,
                                             'templates', fnt)

                if not os.path.exists(fnd):
                    of = task_vars.get('_original_file', None)
                    if of is not None:
                        fnd = self._loader.path_dwim(
                            self._task._role_._role_path, 'templates', of)

                if os.path.exists(fnd):
                    source = fnd
                    found = True
                    break
            if not found:
                return dict(
                    failed=True,
                    msg="could not find src in first_available_file list")
        else:
            if self._task._role is not None:
                source = self._loader.path_dwim_relative(
                    self._task._role._role_path, 'templates', source)
            else:
                source = self._loader.path_dwim(source)

        # Expand any user home dir specification
        dest = self._remote_expand_user(dest, tmp)

        directory_prepended = False
        if dest.endswith(os.sep):
            directory_prepended = True
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            with open(source, 'r') as f:
                template_data = f.read()

            try:
                template_uid = pwd.getpwuid(os.stat(source).st_uid).pw_name
            except:
                template_uid = os.stat(source).st_uid

            vars = task_vars.copy()
            vars['template_host'] = os.uname()[1]
            vars['template_path'] = source
            vars['template_mtime'] = datetime.datetime.fromtimestamp(
                os.path.getmtime(source))
            vars['template_uid'] = template_uid
            vars['template_fullpath'] = os.path.abspath(source)
            vars['template_run_date'] = datetime.datetime.now()

            managed_default = C.DEFAULT_MANAGED_STR
            managed_str = managed_default.format(host=vars['template_host'],
                                                 uid=vars['template_uid'],
                                                 file=to_bytes(
                                                     vars['template_path']))
            vars['ansible_managed'] = time.strftime(
                managed_str, time.localtime(os.path.getmtime(source)))

            old_vars = self._templar._available_variables
            self._templar.set_available_variables(vars)
            resultant = self._templar.template(template_data,
                                               preserve_trailing_newlines=True)
            self._templar.set_available_variables(old_vars)
        except Exception as e:
            return dict(failed=True, msg=type(e).__name__ + ": " + str(e))

        local_checksum = checksum_s(resultant)
        remote_checksum = self.get_checksum(tmp,
                                            dest,
                                            not directory_prepended,
                                            source=source)
        if isinstance(remote_checksum, dict):
            # Error from remote_checksum is a dict.  Valid return is a str
            return remote_checksum

        if local_checksum != remote_checksum:
            # if showing diffs, we need to get the remote value
            dest_contents = ''

            # FIXME: still need to implement diff mechanism
            #if self.runner.diff:
            #    # using persist_files to keep the temp directory around to avoid needing to grab another
            #    dest_result = self.runner._execute_module(conn, tmp, 'slurp', "path=%s" % dest, task_vars=task_vars, persist_files=True)
            #    if 'content' in dest_result.result:
            #        dest_contents = dest_result.result['content']
            #        if dest_result.result['encoding'] == 'base64':
            #            dest_contents = base64.b64decode(dest_contents)
            #        else:
            #            raise Exception("unknown encoding, failed: %s" % dest_result.result)

            xfered = self._transfer_data(
                self._connection._shell.join_path(tmp, 'source'), resultant)

            # fix file permissions when the copy is done as a different user
            if self._connection_info.become and self._connection_info.become_user != 'root':
                self._remote_chmod('a+r', xfered, tmp)

            # run the copy module
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=xfered,
                    dest=dest,
                    original_basename=os.path.basename(source),
                    follow=True,
                ), )

            result = self._execute_module(module_name='copy',
                                          module_args=new_module_args,
                                          task_vars=task_vars)
            if result.get('changed', False):
                result['diff'] = dict(before=dest_contents, after=resultant)
            return result

        else:
            # when running the file module based on the template data, we do
            # not want the source filename (the name of the template) to be used,
            # since this would mess up links, so we clear the src param and tell
            # the module to follow links.  When doing that, we have to set
            # original_basename to the template just in case the dest is
            # a directory.
            new_module_args = self._task.args.copy()
            new_module_args.update(
                dict(
                    src=None,
                    original_basename=os.path.basename(source),
                    follow=True,
                ), )

            return self._execute_module(module_name='file',
                                        module_args=new_module_args,
                                        task_vars=task_vars)