Example #1
0
        def generate_filenames(host, inject, filename):

            """ Render the raw filename into 3 forms """

            # filename2 is the templated version of the filename, which will
            # be fully rendered if any variables contained within it are 
            # non-inventory related
            filename2 = template(self.basedir, filename, self.vars)

            # filename3 is the same as filename2, but when the host object is
            # available, inventory variables will be expanded as well since the
            # name is templated with the injected variables
            filename3 = filename2
            if host is not None:
                filename3 = template(self.basedir, filename2, inject)

            # filename4 is the dwim'd path, but may also be mixed-scope, so we use
            # both play scoped vars and host scoped vars to template the filepath
            if self._has_vars_in(filename3) and host is not None:
                inject.update(self.vars)
                filename4 = template(self.basedir, filename3, inject)
                filename4 = utils.path_dwim(self.basedir, filename4)
            else:
                filename4 = utils.path_dwim(self.basedir, filename3)

            return filename2, filename3, filename4
Example #2
0
def check_conditional(conditional, basedir, inject, fail_on_undefined=False, jinja2=False):

    if jinja2:
        conditional = "jinja2_compare %s" % conditional

    if conditional.startswith("jinja2_compare"):
        conditional = conditional.replace("jinja2_compare ","")
        # allow variable names
        if conditional in inject:
            conditional = inject[conditional]
        conditional = template.template(basedir, conditional, inject, fail_on_undefined=fail_on_undefined)
        # a Jinja2 evaluation that results in something Python can eval!
        presented = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
        conditional = template.template(basedir, presented, inject)
        val = conditional.lstrip().rstrip()
        if val == "True":
            return True
        elif val == "False":
            return False
        else:
            raise errors.AnsibleError("unable to evaluate conditional: %s" % conditional)

    if not isinstance(conditional, basestring):
        return conditional

    try:
        conditional = conditional.replace("\n", "\\n")
        result = safe_eval(conditional)
        if result not in [ True, False ]:
            raise errors.AnsibleError("Conditional expression must evaluate to True or False: %s" % conditional)
        return result

    except (NameError, SyntaxError):
        raise errors.AnsibleError("Could not evaluate the expression: (%s)" % conditional)
Example #3
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' handler for template operations '''

        # note: since this module just calls the copy module, the --check mode support
        # can be implemented entirely over there

        if not self.runner.is_playbook:
            raise errors.AnsibleError("in current versions of ansible, templates are only usable in playbooks")

        # load up options
        options  = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))

        source   = options.get('src', None)
        dest     = options.get('dest', None)

        if (source is None and 'first_available_file' not in inject) or dest is None:
            result = dict(failed=True, msg="src and dest are required")
            return ReturnData(conn=conn, comm_ok=False, result=result)

        # 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 inject:
            found = False
            for fn in self.runner.module_vars.get('first_available_file'):
                fn_orig = fn
                fnt = template.template(self.runner.basedir, fn, inject)
                fnd = utils.path_dwim(self.runner.basedir, fnt)
                if not os.path.exists(fnd) and '_original_file' in inject:
                    fnd = utils.path_dwim_relative(inject['_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:
            source = template.template(self.runner.basedir, source, inject)
                
            if '_original_file' in inject:
                source = utils.path_dwim_relative(inject['_original_file'], 'templates', source, self.runner.basedir)
            else:
                source = utils.path_dwim(self.runner.basedir, source)


        if dest.endswith("/"): # CCTODO: Fix path for Windows hosts.
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            resultant = template.template_from_file(self.runner.basedir, source, inject, vault_password=self.runner.vault_pass)
        except Exception, e:
            result = dict(failed=True, msg=type(e).__name__ + ": " + str(e))
            return ReturnData(conn=conn, comm_ok=False, result=result)
Example #4
0
    def run(self, conn, tmp, module_name, module_args, inject,
            complex_args=None, **kwargs):
        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(utils.parse_kv(module_args))

        dest = args.get('dest')
        extra_vars = args.get('vars')
        sources = args.get('sources')

        if extra_vars:
            # Extend 'inject' args used in templating
            if isinstance(extra_vars, dict):
                inject.update(extra_vars)
            else:
                inject.update(utils.parse_kv(extra_vars))

        # Catch the case where sources is a str()
        if not isinstance(sources, list):
            sources = [sources]

        config = ConfigParser()

        for source in sources:
            # template the source string
            source = template.template(self.runner.basedir, source, inject)

            try:
                self.read_config(source, inject, config)
            except Exception as e:
                return ReturnData(conn=conn, comm_ok=False,
                                  result={'failed': True, 'msg': str(e)})

        # Dump configparser to string via an emulated file
        fakefile = StringIO()
        config.write(fakefile)
        # Template the file to fill out any variables
        content = template.template(self.runner.basedir, fakefile.getvalue(),
                                    inject)
        fakefile.close()

        # Ship this content over to a new file for use with the copy module
        xfered = self.runner._transfer_str(conn, tmp, 'source', content)

        copy_module_args = dict(
            src=xfered,
            dest=dest,
            original_basename=os.path.basename(source),
            follow=True,
        )
        return self.runner._execute_module(conn, tmp, 'copy', '',
                                           inject=inject,
                                           complex_args=copy_module_args)
Example #5
0
def check_conditional(conditional, basedir, inject, fail_on_undefined=False, jinja2=False):

    if isinstance(conditional, list):
        for x in conditional:
            if not check_conditional(x, basedir, inject, fail_on_undefined=fail_on_undefined, jinja2=jinja2):
                return False
        return True

    if jinja2:
        conditional = "jinja2_compare %s" % conditional

    if conditional.startswith("jinja2_compare"):
        conditional = conditional.replace("jinja2_compare ", "")
        # allow variable names
        if conditional in inject and str(inject[conditional]).find("-") == -1:
            conditional = inject[conditional]
        conditional = template.template(basedir, conditional, inject, fail_on_undefined=fail_on_undefined)
        original = str(conditional).replace("jinja2_compare ", "")
        # a Jinja2 evaluation that results in something Python can eval!
        presented = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
        conditional = template.template(basedir, presented, inject)
        val = conditional.strip()
        if val == presented:
            # the templating failed, meaning most likely a
            # variable was undefined. If we happened to be
            # looking for an undefined variable, return True,
            # otherwise fail
            if conditional.find("is undefined") != -1:
                return True
            elif conditional.find("is defined") != -1:
                return False
            else:
                raise errors.AnsibleError("error while evaluating conditional: %s" % original)
        elif val == "True":
            return True
        elif val == "False":
            return False
        else:
            raise errors.AnsibleError("unable to evaluate conditional: %s" % original)

    if not isinstance(conditional, basestring):
        return conditional

    try:
        conditional = conditional.replace("\n", "\\n")
        result = safe_eval(conditional)
        if result not in [True, False]:
            raise errors.AnsibleError("Conditional expression must evaluate to True or False: %s" % conditional)
        return result

    except (NameError, SyntaxError):
        raise errors.AnsibleError("Could not evaluate the expression: (%s)" % conditional)
Example #6
0
    def _process_include(self, data, basedir, vars={}):

        tokens = shlex.split(data['include'])

        defaults = vars.copy()

        # allow key=value parameters to be specified on the include line
        # to set variables

        for t in tokens[1:]:
            (k, v) = t.split("=", 1)
            defaults[k] = template(basedir, v, defaults)

        included_path = utils.path_dwim(basedir, template(basedir, tokens[0], defaults))
        return self._load_play_from_file(included_path, defaults)
Example #7
0
    def run(self, terms, inject=None, **kwargs):
        ''' Main execution path '''

        try:
            terms = template.template(self.basedir, terms, inject)
        # Reason: disable broad-except to really ignore any potential exception
        #         This is inspired by the upstream "env" lookup plugin:
        #         https://github.com/ansible/ansible/blob/devel/v1/ansible/runner/lookup_plugins/env.py#L29
        # pylint: disable=broad-except
        except Exception:
            pass

        if isinstance(terms, basestring):
            terms = [terms]

        ret = []

        for term in terms:
            option_name = term.split()[0]
            cli_key = 'cli_' + option_name
            if inject and cli_key in inject:
                ret.append(inject[cli_key])
            elif option_name in os.environ:
                ret.append(os.environ[option_name])
            else:
                ret.append('')

        return ret
  def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

    if not module_args:
      result = dict(failed=True, msg="No source file given")
      return ReturnData(conn=conn, comm_ok=True, result=result)

    source = template.template(self.runner.basedir, module_args, inject)

    if '_original_file' in inject:
      source = utils.path_dwim_relative(inject['_original_file'], 'vars', source, self.runner.basedir, False)
    else:
      source = utils.path_dwim(self.runner.basedir, source)

    data = {}

    if os.path.exists(source):
      data = utils.parse_yaml_from_file(source, vault_password=self.runner.vault_pass)

      if data and type(data) != dict:
        raise errors.AnsibleError("%s must be stored as a dictionary/hash" % source)

    if not hasattr(conn.runner, 'mergeBuffer'):
      conn.runner.mergeBuffer = {}

    if conn.host in conn.runner.mergeBuffer:
      data = utils.merge_hash(conn.runner.mergeBuffer[conn.host], data)

    conn.runner.mergeBuffer[conn.host] = data

    result = dict(ansible_facts=data)
    return ReturnData(conn=conn, comm_ok=True, result=result)
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        try:

            args = {}
            if complex_args:
                args.update(complex_args)
            args.update(parse_kv(module_args))

            envdict={}
            if self.runner.environment:
                env=template.template(self.runner.basedir, self.runner.environment, inject, convert_bare=True)
                env = utils.safe_eval(env)

            testQueue = args["queue_name"]
            region = args["region"]

            spec_file = path.expanduser("~/.nucleator/contrib/Bucketandq/orchestrator/specification.json")

            queue = self.initQueue(testQueue, region, env)
            self.main(self.addMessageToQueue, queue, spec_file)

            return ReturnData(conn=conn,
                comm_ok=True,
                result=dict(failed=False, changed=False, msg="Bucketandq Messages Created!"))

        except Exception, e:
            # deal with failure gracefully
            result = dict(failed=True, msg=type(e).__name__ + ": " + str(e))
            return ReturnData(conn=conn, comm_ok=False, result=result)
Example #10
0
    def _get_role_path(self, role):
        """
        Returns the path on disk to the directory containing
        the role directories like tasks, templates, etc. Also 
        returns any variables that were included with the role
        """
        orig_path = template(self.basedir,role,self.vars)

        role_vars = {}
        if type(orig_path) == dict:
            # what, not a path?
            role_name = orig_path.get('role', None)
            if role_name is None:
                raise errors.AnsibleError("expected a role name in dictionary: %s" % orig_path)
            role_vars = orig_path
            orig_path = role_name

        path = utils.path_dwim(self.basedir, os.path.join('roles', orig_path))
        if not os.path.isdir(path) and not orig_path.startswith(".") and not orig_path.startswith("/"):
            path2 = utils.path_dwim(self.basedir, orig_path)
            if not os.path.isdir(path2):
                raise errors.AnsibleError("cannot find role in %s or %s" % (path, path2))
            path = path2
        elif not os.path.isdir(path):
            raise errors.AnsibleError("cannot find role in %s" % (path))

        return (path, role_vars)
Example #11
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        args = {}
        if complex_args:
            args.update(complex_args)

        # attempt to prevent confusing messages when the variable didn't interpolate
        module_args = module_args.replace("{{ ","{{").replace(" }}","}}")

        kv = utils.parse_kv(module_args)
        args.update(kv)

        if not 'msg' in args and not 'var' in args:
            args['msg'] = 'Hello world!'

        result = {}
        if 'msg' in args:
            if 'fail' in args and utils.boolean(args['fail']):
                result = dict(failed=True, msg=args['msg'])
            else:
                result = dict(msg=args['msg'])
        elif 'var' in args and not utils.LOOKUP_REGEX.search(args['var']):
            results = template.template(self.basedir, args['var'], inject, convert_bare=True)
            result[args['var']] = results

        # force flag to make debug output module always verbose
        result['verbose_always'] = True

        return ReturnData(conn=conn, result=result)
Example #12
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' run the pause action module '''

        # note: this module does not need to pay attention to the 'check'
        # flag, it always runs

        hosts = ', '.join(self.runner.host_set)
        args = {}
        if complex_args:
            args.update(complex_args)
        # extra template call unneeded?
        args.update(parse_kv(template.template(self.runner.basedir, module_args, inject)))

        # Are 'minutes' or 'seconds' keys that exist in 'args'?
        if 'minutes' in args or 'seconds' in args:
            try:
                if 'minutes' in args:
                    self.pause_type = 'minutes'
                    # The time() command operates in seconds so we need to
                    # recalculate for minutes=X values.
                    self.seconds = int(args['minutes']) * 60
                else:
                    self.pause_type = 'seconds'
                    self.seconds = int(args['seconds'])
                    self.duration_unit = 'seconds'
            except ValueError, e:
                raise ae("non-integer value given for prompt duration:\n%s" % str(e))
Example #13
0
def listify_lookup_plugin_terms(terms, basedir, inject):

    if isinstance(terms, basestring):
        # someone did:
        #    with_items: alist
        # OR
        #    with_items: {{ alist }}

        stripped = terms.strip()
        if not (stripped.startswith('{') or stripped.startswith('[')) and not stripped.startswith("/"):
            # if not already a list, get ready to evaluate with Jinja2
            # not sure why the "/" is in above code :)
            try:
                new_terms = template.template(basedir, "{{ %s }}" % terms, inject)
                if isinstance(new_terms, basestring) and new_terms.find("{{") != -1:
                    pass
                else:
                    terms = new_terms
            except:
                pass

        if '{' in terms or '[' in terms:
            # Jinja2 already evaluated a variable to a list.
            # Jinja2-ified list needs to be converted back to a real type
            # TODO: something a bit less heavy than eval
            return safe_eval(terms)

        if isinstance(terms, basestring):
            terms = [ terms ]

    return terms
Example #14
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        if not module_args:
            result = dict(failed=True, msg="No source file given")
            return ReturnData(conn=conn, comm_ok=True, result=result)

        source = module_args
        source = template.template(self.runner.basedir, source, inject)

        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'], 'vars', source, self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        if os.path.exists(source):
            data = utils.parse_yaml_from_file(source, vault_password=self.runner.vault_pass)
            if data and type(data) != dict:
                raise errors.AnsibleError("%s must be stored as a dictionary/hash" % source)
            elif data is None:
                data = {}
            result = dict(ansible_facts=data)
            return ReturnData(conn=conn, comm_ok=True, result=result)
        else:
            result = dict(failed=True, msg="Source file not found.", file=source)
            return ReturnData(conn=conn, comm_ok=True, result=result)
Example #15
0
        def generate_filenames(host, inject, filename):

            """ Render the raw filename into 3 forms """

            filename2 = template(self.basedir, filename, self.vars)
            filename3 = filename2
            if host is not None:
                filename3 = template(self.basedir, filename2, inject)
            if self._has_vars_in(filename3) and host is not None:
                # allow play scoped vars and host scoped vars to template the filepath
                inject.update(self.vars)
                filename4 = template(self.basedir, filename3, inject)
                filename4 = utils.path_dwim(self.basedir, filename4)
            else:    
                filename4 = utils.path_dwim(self.basedir, filename3)
            return filename2, filename3, filename4
Example #16
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):

        # the group_by module does not need to pay attention to check mode.
        # it always runs.

        args = {}
        if complex_args:
            args.update(complex_args)
        args.update(parse_kv(self.runner.module_args))
        if not 'key' in args:
            raise ae("'key' is a required argument.")

        vv("created 'group_by' ActionModule: key=%s"%(args['key']))

        inventory = self.runner.inventory

        result = {'changed': False}

        ### find all groups
        groups = {}

        for host in self.runner.host_set:
            data = {}
            data.update(inject)
            data.update(inject['hostvars'][host])
            conds = self.runner.conditional
            if type(conds) != list:
                conds = [ conds ]
            next_host = False
            for cond in conds:
                if not check_conditional(cond, self.runner.basedir, data, fail_on_undefined=self.runner.error_on_undefined_vars):
                    next_host = True
                    break
            if next_host:
                continue
            group_name = template.template(self.runner.basedir, args['key'], data)
            group_name = group_name.replace(' ','-')
            if group_name not in groups:
                groups[group_name] = []
            groups[group_name].append(host)

        result['groups'] = groups

        ### add to inventory
        for group, hosts in groups.items():
            inv_group = inventory.get_group(group)
            if not inv_group:
                inv_group = ansible.inventory.Group(name=group)
                inventory.add_group(inv_group)
            for host in hosts:
                del self.runner.inventory._vars_per_host[host]
                inv_host = inventory.get_host(host)
                if not inv_host:
                    inv_host = ansible.inventory.Host(name=host)
                if inv_group not in inv_host.get_groups():
                    result['changed'] = True
                    inv_group.add_host(inv_host)

        return ReturnData(conn=conn, comm_ok=True, result=result)
Example #17
0
    def run(self, terms, variables, **kwargs):

        if isNotV2:
            try:
                inject = variables['inject'] if 'inject' in variables else None
                key = template.template(self.basedir, terms[0], inject)
            except Exception, e:
                pass
Example #18
0
    def _arg_or_fact(self, arg_name, fact_name, args, inject):
        res = args.get(arg_name)
        if res is not None:
            return res

        template_string = '{{ %s }}' % fact_name
        res = template.template(self.basedir, template_string, inject)
        return None if res == template_string else res
Example #19
0
    def _prepare_settings(self, settings, default_vars, extra_vars):

        combined_vars = ansible.utils.combine_vars(default_vars, extra_vars)

        for k, v in settings.iteritems():
            settings[k] = template(self.basedir, v, combined_vars)

        return settings
Example #20
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' handler for file transfer operations '''

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))
        source  = options.get('src', None)
        dest    = options.get('dest', None)
        copy    = utils.boolean(options.get('copy', 'yes'))

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

        dest = os.path.expanduser(dest) # CCTODO: Fix path for Windows hosts.
        source = template.template(self.runner.basedir, os.path.expanduser(source), inject)
        if copy:
            if '_original_file' in inject:
                source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir)
            else:
                source = utils.path_dwim(self.runner.basedir, source)

        remote_md5 = self.runner._remote_md5(conn, tmp, dest)
        if remote_md5 != '3':
            result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest)
            return ReturnData(conn=conn, result=result)

        if copy:
            # transfer the file to a remote tmp location
            tmp_src = tmp + 'source'
            conn.put_file(source, tmp_src)

        # handle diff mode client side
        # handle check mode client side
        # fix file permissions when the copy is done as a different user
        if copy:
            if self.runner.sudo and self.runner.sudo_user != 'root' or self.runner.su and self.runner.su_user != 'root':
                if not self.runner.noop_on_check(inject):
                    self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp)
            # Build temporary module_args.
            new_module_args = dict(
                src=tmp_src,
                original_basename=os.path.basename(source),
            )

            # make sure checkmod is passed on correctly
            if self.runner.noop_on_check(inject):
                new_module_args['CHECKMODE'] = True

            module_args = utils.merge_module_args(module_args, new_module_args)
        else:
            module_args = "%s original_basename=%s" % (module_args, pipes.quote(os.path.basename(source)))
            # make sure checkmod is passed on correctly
            if self.runner.noop_on_check(inject):
                module_args += " CHECKMODE=True"
        return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        """Run the method"""
        if not self.runner.is_playbook:
            raise errors.AnsibleError("FAILED: `config_templates` are only available in playbooks")

        options = self.grab_options(complex_args, module_args)
        try:
            source = options["src"]
            dest = options["dest"]

            config_overrides = options.get("config_overrides", dict())
            config_type = options["config_type"]
            assert config_type.lower() in ["ini", "json", "yaml"]
        except KeyError as exp:
            result = dict(failed=True, msg=exp)
            return ReturnData(conn=conn, comm_ok=False, result=result)

        source_template = template.template(self.runner.basedir, source, inject)

        if "_original_file" in inject:
            source_file = utils.path_dwim_relative(
                inject["_original_file"], "templates", source_template, self.runner.basedir
            )
        else:
            source_file = utils.path_dwim(self.runner.basedir, source_template)

        # Open the template file and return the data as a string. This is
        #  being done here so that the file can be a vault encrypted file.
        resultant = template.template_from_file(
            self.runner.basedir, source_file, inject, vault_password=self.runner.vault_pass
        )

        if config_overrides:
            type_merger = getattr(self, CONFIG_TYPES.get(config_type))
            resultant = type_merger(config_overrides=config_overrides, resultant=resultant)

        # Retemplate the resultant object as it may have new data within it
        #  as provided by an override variable.
        template.template_from_string(basedir=self.runner.basedir, data=resultant, vars=inject, fail_on_undefined=True)

        # Access to protected method is unavoidable in Ansible 1.x.
        new_module_args = dict(
            src=self.runner._transfer_str(conn, tmp, "source", resultant),
            dest=dest,
            original_basename=os.path.basename(source),
            follow=True,
        )

        module_args_tmp = utils.merge_module_args(module_args, new_module_args)

        # Remove data types that are not available to the copy module
        complex_args.pop("config_overrides")
        complex_args.pop("config_type")

        # Return the copy module status. Access to protected method is
        #  unavoidable in Ansible 1.x.
        return self.runner._execute_module(conn, tmp, "copy", module_args_tmp, inject=inject, complex_args=complex_args)
Example #22
0
    def _load_playbook_from_file(self, path, vars={}, vars_files=[]):
        '''
        run top level error checking on playbooks and allow them to include other playbooks.
        '''

        playbook_data = utils.parse_yaml_from_file(
            path, vault_password=self.vault_password)
        accumulated_plays = []
        play_basedirs = []

        if type(playbook_data) != list:
            raise errors.AnsibleError(
                "parse error: playbooks must be formatted as a YAML list, got %s"
                % type(playbook_data))

        basedir = os.path.dirname(path) or '.'
        utils.plugins.push_basedir(basedir)
        for play in playbook_data:
            if type(play) != dict:
                raise errors.AnsibleError(
                    "parse error: each play in a playbook must be a YAML dictionary (hash), received: %s"
                    % play)

            if 'include' in play:
                # a playbook (list of plays) decided to include some other list of plays
                # from another file.  The result is a flat list of plays in the end.

                play_vars = self._get_playbook_vars(play, vars)
                play_vars_files = self._get_playbook_vars_files(
                    play, vars_files)
                inc_vars, inc_path = self._get_include_info(
                    play, basedir, play_vars)
                play_vars.update(inc_vars)

                included_path = utils.path_dwim(
                    basedir, template(basedir, inc_path, play_vars))
                (plays, basedirs) = self._load_playbook_from_file(
                    included_path, vars=play_vars, vars_files=play_vars_files)
                for p in plays:
                    # support for parameterized play includes works by passing
                    # those variables along to the subservient play
                    p['vars'] = self._extend_play_vars(p, play_vars)
                    # now add in the vars_files
                    p['vars_files'] = utils.list_union(p.get('vars_files', []),
                                                       play_vars_files)

                accumulated_plays.extend(plays)
                play_basedirs.extend(basedirs)

            else:

                # this is a normal (non-included play)
                accumulated_plays.append(play)
                play_basedirs.append(basedir)

        return (accumulated_plays, play_basedirs)
Example #23
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        ''' handler for file transfer operations '''

        if self.runner.check:
            # in check mode, always skip this module
            return ReturnData(
                conn=conn,
                comm_ok=True,
                result=dict(skipped=True,
                            msg='check mode not supported for this module'))

        tokens = shlex.split(module_args)
        source = tokens[0]
        # FIXME: error handling
        args = " ".join(tokens[1:])
        source = template.template(self.runner.basedir, source, inject)
        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'],
                                              'files', source,
                                              self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        # transfer the file to a remote tmp location
        source = source.replace('\x00', '')  # why does this happen here?
        args = args.replace('\x00', '')  # why does this happen here?
        tmp_src = os.path.join(tmp, os.path.basename(source))
        tmp_src = tmp_src.replace('\x00', '')

        conn.put_file(source, tmp_src)

        # fix file permissions when the copy is done as a different user
        if self.runner.sudo and self.runner.sudo_user != 'root':
            prepcmd = 'chmod a+rx %s' % tmp_src
        else:
            prepcmd = 'chmod +x %s' % tmp_src

        # add preparation steps to one ssh roundtrip executing the script
        module_args = prepcmd + '; ' + tmp_src + ' ' + args

        handler = utils.plugins.action_loader.get('raw', self.runner)
        result = handler.run(conn, tmp, 'raw', module_args, inject)

        # clean up after
        if tmp.find("tmp") != -1 and C.DEFAULT_KEEP_REMOTE_FILES != '1':
            self.runner._low_level_exec_command(
                conn, 'rm -rf %s >/dev/null 2>&1' % tmp, tmp)

        return result
Example #24
0
    def _load_playbook_from_file(self, path, vars={}, vars_files=[]):
        '''
        run top level error checking on playbooks and allow them to include other playbooks.
        '''

        playbook_data  = utils.parse_yaml_from_file(path, vault_password=self.vault_password)
        accumulated_plays = []
        play_basedirs = []

        if type(playbook_data) != list:
            raise errors.AnsibleError("parse error: playbooks must be formatted as a YAML list, got %s" % type(playbook_data))

        basedir = os.path.dirname(path) or '.'
        utils.plugins.push_basedir(basedir)
        for play in playbook_data:
            if type(play) != dict:
                raise errors.AnsibleError("parse error: each play in a playbook must be a YAML dictionary (hash), recieved: %s" % play)

            if 'include' in play:
                # a playbook (list of plays) decided to include some other list of plays
                # from another file.  The result is a flat list of plays in the end.

                play_vars = self._get_playbook_vars(play, vars)
                play_vars_files = self._get_playbook_vars_files(play, vars_files)
                inc_vars, inc_path = self._get_include_info(play, basedir, play_vars)
                play_vars.update(inc_vars)

                included_path = utils.path_dwim(basedir, template(basedir, inc_path, play_vars))
                (plays, basedirs) = self._load_playbook_from_file(included_path, vars=play_vars, vars_files=play_vars_files)
                for p in plays:
                    # support for parameterized play includes works by passing
                    # those variables along to the subservient play
                    if 'vars' not in p:
                        p['vars'] = {}
                    if isinstance(p['vars'], dict):
                        p['vars'].update(play_vars)
                    elif isinstance(p['vars'], list):
                        # nobody should really do this, but handle vars: a=1 b=2
                        p['vars'].extend([{k:v} for k,v in play_vars.iteritems()])
                    elif p['vars'] == None:
                        # someone specified an empty 'vars:', so reset
                        # it to the vars we currently have
                        p['vars'] = play_vars.copy()
                    # now add in the vars_files
                    p['vars_files'] = utils.list_union(p.get('vars_files', []), play_vars_files)

                accumulated_plays.extend(plays)
                play_basedirs.extend(basedirs)

            else:

                # this is a normal (non-included play)
                accumulated_plays.append(play)
                play_basedirs.append(basedir)

        return (accumulated_plays, play_basedirs)
Example #25
0
 def test_varReplace_var_complex_var(self):
     vars = {
         'x': '$y',
         'y': {
             'foo': 'result',
         },
     }
     template = '${x.foo}'
     res = template2.template(None, template, vars)
     assert res == 'result'
Example #26
0
    def test_template_varReplace_iterated(self):
        template = 'hello $who'
        vars = {
            'who': 'oh great $person',
            'person': 'one',
        }

        res = template2.template(None, template, vars)

        assert res == u'hello oh great one'
Example #27
0
    def test_template_varReplace_iterated(self):
        template = 'hello $who'
        vars = {
            'who': 'oh great $person',
            'person': 'one',
        }

        res = template2.template(None, template, vars)

        assert res == u'hello oh great one'
Example #28
0
 def test_varReplace_var_complex_var(self):
     vars = {
         'x': '$y',
         'y': {
             'foo': 'result',
         },
     }
     template = '${x.foo}'
     res = template2.template(None, template, vars)
     assert res == 'result'
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        ''' handler for file transfer operations '''

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))
        source = options.get('src', None)
        dest = options.get('dest', None)

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

        source = template.template(self.runner.basedir, source, inject)
        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'],
                                              'files', source,
                                              self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        remote_md5 = self.runner._remote_md5(conn, tmp, dest)
        if remote_md5 != '3':
            result = dict(failed=True, msg="dest must be an existing dir")
            return ReturnData(conn=conn, result=result)

        # transfer the file to a remote tmp location
        tmp_src = tmp + 'source'
        conn.put_file(source, tmp_src)

        # handle diff mode client side
        # handle check mode client side
        # fix file permissions when the copy is done as a different user
        if self.runner.sudo and self.runner.sudo_user != 'root':
            self.runner._low_level_exec_command(conn, "chmod a+r %s" % tmp_src,
                                                tmp)
        module_args = "%s src=%s original_basename=%s" % (
            module_args, pipes.quote(tmp_src),
            pipes.quote(os.path.basename(source)))
        return self.runner._execute_module(conn,
                                           tmp,
                                           'unarchive',
                                           module_args,
                                           inject=inject,
                                           complex_args=complex_args)
Example #30
0
def check_conditional(conditional, basedir, inject, fail_on_undefined=False):
    from ansible.utils import template

    if conditional is None or conditional == '':
        return True

    if isinstance(conditional, list):
        for x in conditional:
            if not check_conditional(x, basedir, inject, fail_on_undefined=fail_on_undefined):
                return False
        return True

    if not isinstance(conditional, basestring):
        return conditional

    conditional = conditional.replace("jinja2_compare ","")
    # allow variable names
    if conditional in inject and '-' not in str(inject[conditional]):
        conditional = inject[conditional]
    conditional = template.template(basedir, conditional, inject, fail_on_undefined=fail_on_undefined)
    original = str(conditional).replace("jinja2_compare ","")
    # a Jinja2 evaluation that results in something Python can eval!
    presented = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
    conditional = template.template(basedir, presented, inject)
    val = conditional.strip()
    if val == presented:
        # the templating failed, meaning most likely a 
        # variable was undefined. If we happened to be 
        # looking for an undefined variable, return True,
        # otherwise fail
        if "is undefined" in conditional:
            return True
        elif "is defined" in conditional:
            return False
        else:
            raise errors.AnsibleError("error while evaluating conditional: %s" % original)
    elif val == "True":
        return True
    elif val == "False":
        return False
    else:
        raise errors.AnsibleError("unable to evaluate conditional: %s" % original)
 def _command_filter(self, command, arg, items, inject):
     """Return only the items for which filter is true"""
     if '{{' not in arg:
         arg = '{{%s}}' % arg
     for item in items:
         template_vars = dict(inject, item=item)
         decision = safe_eval(
             template(self.basedir, arg, template_vars),
             locals=template_vars)
         if decision:
             yield item
 def get_value(self, varname):
     """Get a variable's value by applying a template.
     If the value is dict or list, *varname* may include '.' or '[]'
     to get the content of dict or list.
     * For example, if the value of variable "var" is {"k": "v"},
       get_value("var.k") will return "v".
     """
     value = template.template('.', '{{ %s }}' % varname, self.task_info.vars)
     if '{{' in value:
         value = 'Not defined'
     return value
Example #33
0
def check_conditional(conditional, basedir, inject, fail_on_undefined=False):

    if conditional is None or conditional == '':
        return True

    if isinstance(conditional, list):
        for x in conditional:
            if not check_conditional(x, basedir, inject, fail_on_undefined=fail_on_undefined):
                return False
        return True

    if not isinstance(conditional, basestring):
        return conditional

    conditional = conditional.replace("jinja2_compare ","")
    # allow variable names
    if conditional in inject and '-' not in str(inject[conditional]):
        conditional = inject[conditional]
    conditional = template.template(basedir, conditional, inject, fail_on_undefined=fail_on_undefined)
    original = str(conditional).replace("jinja2_compare ","")
    # a Jinja2 evaluation that results in something Python can eval!
    presented = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
    conditional = template.template(basedir, presented, inject)
    val = conditional.strip()
    if val == presented:
        # the templating failed, meaning most likely a 
        # variable was undefined. If we happened to be 
        # looking for an undefined variable, return True,
        # otherwise fail
        if "is undefined" in conditional:
            return True
        elif "is defined" in conditional:
            return False
        else:
            raise errors.AnsibleError("error while evaluating conditional: %s" % original)
    elif val == "True":
        return True
    elif val == "False":
        return False
    else:
        raise errors.AnsibleError("unable to evaluate conditional: %s" % original)
Example #34
0
File: copy.py Project: jmjf/ansible
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' handler for file transfer operations '''

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))
        source  = options.get('src', None)
        content = options.get('content', None)
        dest    = options.get('dest', None)
        raw     = utils.boolean(options.get('raw', 'no'))
        force   = utils.boolean(options.get('force', 'yes'))

        if (source is None and content is None and not 'first_available_file' in inject) or dest is None:
            result=dict(failed=True, msg="src (or content) and dest are required")
            return ReturnData(conn=conn, result=result)
        elif (source is not None or 'first_available_file' in inject) and content is not None:
            result=dict(failed=True, msg="src and content are mutually exclusive")
            return ReturnData(conn=conn, result=result)

        source_trailing_slash = False
        if source:
            source_trailing_slash = source.endswith("/")

        # 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 inject:
            found = False
            for fn in inject.get('first_available_file'):
                fn_orig = fn
                fnt = template.template(self.runner.basedir, fn, inject)
                fnd = utils.path_dwim(self.runner.basedir, fnt)
                if not os.path.exists(fnd) and '_original_file' in inject:
                    fnd = utils.path_dwim_relative(inject['_original_file'], 'files', fnt, self.runner.basedir, check=False)
                if os.path.exists(fnd):
                    source = fnd
                    found = True
                    break
            if not found:
                results=dict(failed=True, msg="could not find src in first_available_file list")
                return ReturnData(conn=conn, result=results)
        elif content is not None:
            fd, tmp_content = tempfile.mkstemp()
            f = os.fdopen(fd, 'w')
            try:
                f.write(content)
            except Exception, err:
                os.remove(tmp_content)
                result = dict(failed=True, msg="could not write content temp file: %s" % err)
                return ReturnData(conn=conn, result=result)
            f.close()
            source = tmp_content
Example #35
0
    def _get_include_info(self, play_ds, basedir, existing_vars={}):
        '''
        Gets any key=value pairs specified with the included file
        name and returns the merged vars along with the path
        '''
        new_vars = existing_vars.copy()
        tokens = shlex.split(play_ds.get('include', ''))
        for t in tokens[1:]:
            (k,v) = t.split("=", 1)
            new_vars[k] = template(basedir, v, new_vars)

        return (new_vars, tokens[0])
Example #36
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' handler for file transfer operations '''

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))
        source  = options.get('src', None)
        content = options.get('content', None)
        dest    = options.get('dest', None)
        raw     = utils.boolean(options.get('raw', 'no'))
        force   = utils.boolean(options.get('force', 'yes'))

        if (source is None and content is None and not 'first_available_file' in inject) or dest is None:
            result=dict(failed=True, msg="src (or content) and dest are required")
            return ReturnData(conn=conn, result=result)
        elif (source is not None or 'first_available_file' in inject) and content is not None:
            result=dict(failed=True, msg="src and content are mutually exclusive")
            return ReturnData(conn=conn, result=result)

        source_trailing_slash = False
        if source:
            source_trailing_slash = source.endswith("/")

        # 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 inject:
            found = False
            for fn in inject.get('first_available_file'):
                fn_orig = fn
                fnt = template.template(self.runner.basedir, fn, inject)
                fnd = utils.path_dwim(self.runner.basedir, fnt)
                if not os.path.exists(fnd) and '_original_file' in inject:
                    fnd = utils.path_dwim_relative(inject['_original_file'], 'files', fnt, self.runner.basedir, check=False)
                if os.path.exists(fnd):
                    source = fnd
                    found = True
                    break
            if not found:
                results=dict(failed=True, msg="could not find src in first_available_file list")
                return ReturnData(conn=conn, result=results)
        elif content is not None:
            fd, tmp_content = tempfile.mkstemp()
            f = os.fdopen(fd, 'w')
            try:
                f.write(content)
            except Exception, err:
                os.remove(tmp_content)
                result = dict(failed=True, msg="could not write content temp file: %s" % err)
                return ReturnData(conn=conn, result=result)
            f.close()
            source = tmp_content
Example #37
0
    def _get_include_info(self, play_ds, basedir, existing_vars={}):
        '''
        Gets any key=value pairs specified with the included file
        name and returns the merged vars along with the path
        '''
        new_vars = existing_vars.copy()
        tokens = shlex.split(play_ds.get('include', ''))
        for t in tokens[1:]:
            (k, v) = t.split("=", 1)
            new_vars[k] = template(basedir, v, new_vars)

        return (new_vars, tokens[0])
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' handler for file transfer operations '''

        if self.runner.noop_on_check(inject):
            # in check mode, always skip this module
            return ReturnData(conn=conn, comm_ok=True, result=dict(skipped=True, msg='check mode not supported for this module'))

        # Decode the result of shlex.split() to UTF8 to get around a bug in that's been fixed in Python 2.7 but not Python 2.6.
        # See: http://bugs.python.org/issue6988
        tokens  = shlex.split(module_args.encode('utf8'))
        tokens = [s.decode('utf8') for s in tokens]

        source  = tokens[0]
        # FIXME: error handling
        args    = " ".join(tokens[1:])
        source  = template.template(self.runner.basedir, source, inject)
        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        # transfer the file to a remote tmp location
        source  = source.replace('\x00','') # why does this happen here?
        args    = args.replace('\x00','') # why does this happen here?
        tmp_src = os.path.join(tmp, os.path.basename(source))
        tmp_src = tmp_src.replace('\x00', '') 

        conn.put_file(source, tmp_src)

        sudoable=True
        # set file permissions, more permisive when the copy is done as a different user
        if self.runner.sudo and self.runner.sudo_user != 'root':
            cmd_args_chmod = "chmod a+rx %s" % tmp_src
            sudoable=False
        else:
            cmd_args_chmod = "chmod +rx %s" % tmp_src
        self.runner._low_level_exec_command(conn, cmd_args_chmod, tmp, sudoable=sudoable)

        # add preparation steps to one ssh roundtrip executing the script
        env_string = self.runner._compute_environment_string(inject)
        module_args = env_string + tmp_src + ' ' + args

        handler = utils.plugins.action_loader.get('raw', self.runner)
        result = handler.run(conn, tmp, 'raw', module_args, inject)

        # clean up after
        if tmp.find("tmp") != -1 and not C.DEFAULT_KEEP_REMOTE_FILES:
            self.runner._low_level_exec_command(conn, 'rm -rf %s >/dev/null 2>&1' % tmp, tmp)

        result.result['changed'] = True

        return result
Example #39
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        args = parse_kv(module_args)
        environment = args.get('environment')
        account_id = args.get('account_id')
        assume_role = args.get('assume_role')

        for name, val in (("environment", environment),
                          ("account_id", account_id), ("assume_role",
                                                       assume_role)):
            if val is None:
                result = dict(failed=True, msg="No {0} specified".format(name))
                return ReturnData(conn=conn, comm_ok=True, result=result)

        source = template.template(self.runner.basedir, environment, inject)

        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'], 'vars',
                                              source, self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        if os.path.exists(source):
            decrypted_data = {}
            data = json.load(open(source))

            with assume(account_id, assume_role):
                kms = boto.kms.connect_to_region('ap-southeast-2')

                for key, val in data.items():
                    data_key = kms.decrypt(base64.b64decode(
                        val['key']))["Plaintext"]
                    content = base64.b64decode(val['content'])
                    counter = Counter.new(128)
                    decryptor = AES.new(data_key[:32],
                                        AES.MODE_CTR,
                                        counter=counter)
                    decrypted_data[key] = decryptor.decrypt(content)

                result = dict(ansible_facts=decrypted_data)
                return ReturnData(conn=conn, comm_ok=True, result=result)
        else:
            result = dict(failed=True,
                          msg="Couldn't find secrets!",
                          file=source)
            return ReturnData(conn=conn, comm_ok=True, result=result)
Example #40
0
    def _compute_environment_string(self, inject=None):
        ''' what environment variables to use when running the command? '''

        if not self.environment:
            return ""
        enviro = template.template(self.basedir, self.environment, inject, convert_bare=True)
        enviro = utils.safe_eval(enviro)
        if type(enviro) != dict:
            raise errors.AnsibleError("environment must be a dictionary, received %s" % enviro)
        result = ""
        for (k,v) in enviro.iteritems():
            result = "%s=%s %s" % (k, pipes.quote(str(v)), result)
        return result
Example #41
0
    def _resolve_file_path(self, filepath, dirname, inject):
        ''' Resolve absolute path of the file. '''

        basedir = self.runner.basedir
        filepath = template.template(basedir, filepath, inject)

        if '_original_file' in inject:
            origin_path = inject['_original_file']
            filepath = utils.path_dwim_relative(origin_path, dirname, filepath, basedir)
        else:
            filepath = utils.path_dwim(basedir, filepath)

        return filepath
Example #42
0
 def _get_include_info(self, play_ds, basedir, existing_vars={}):
     '''
     Gets any key=value pairs specified with the included file
     name and returns the merged vars along with the path
     '''
     new_vars = existing_vars.copy()
     tokens = split_args(play_ds.get('include', ''))
     for t in tokens[1:]:
         try:
             (k,v) = unquote(t).split("=", 1)
             new_vars[k] = template(basedir, v, new_vars)
         except ValueError, e:
             raise errors.AnsibleError('included playbook variables must be in the form k=v, got: %s' % t)
    def _load_tasks(self, tasks, vars={}, default_vars={}, sudo_vars={}, additional_conditions=[], original_file=None):
        ''' handle task and handler include statements '''

        results = []
        if tasks is None:
            # support empty handler files, and the like.
            tasks = []

        for x in tasks:
            if not isinstance(x, dict):
                raise errors.AnsibleError("expecting dict; got: %s" % x)

            # evaluate sudo vars for current and child tasks 
            included_sudo_vars = {}
            for k in ["sudo", "sudo_user"]:
                if k in x:
                    included_sudo_vars[k] = x[k]
                elif k in sudo_vars:
                    included_sudo_vars[k] = sudo_vars[k]
                    x[k] = sudo_vars[k]

            if 'meta' in x:
                if x['meta'] == 'flush_handlers':
                    results.append(Task(self,x))
                    continue

            task_vars = self.vars.copy()
            task_vars.update(vars)
            if original_file:
                task_vars['_original_file'] = original_file

            if 'include' in x:
                tokens = shlex.split(str(x['include']))
                items = ['']
                included_additional_conditions = list(additional_conditions)
                include_vars = {}
                for k in x:
                    if k.startswith("with_"):
                        plugin_name = k[5:]
                        if plugin_name not in utils.plugins.lookup_loader:
                            raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
                        terms = template(self.basedir, x[k], task_vars)
                        items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars)
                    elif k.startswith("when_"):
                        included_additional_conditions.insert(0, utils.compile_when_to_only_if("%s %s" % (k[5:], x[k])))
                    elif k == 'when':
                        included_additional_conditions.insert(0, utils.compile_when_to_only_if("jinja2_compare %s" % x[k]))
                    elif k in ("include", "vars", "default_vars", "only_if", "sudo", "sudo_user"):
                        continue
                    else:
                        include_vars[k] = x[k]
Example #44
0
def check_conditional(conditional, basedir, inject, fail_on_undefined=False):

    if conditional.startswith("jinja2_compare"):
        conditional = conditional.replace("jinja2_compare ", "")
        # allow variable names
        if conditional in inject:
            conditional = inject[conditional]
        conditional = template.template(basedir,
                                        conditional,
                                        inject,
                                        fail_on_undefined=fail_on_undefined)
        # a Jinja2 evaluation that results in something Python can eval!
        presented = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
        conditional = template.template(basedir, presented, inject)
        val = conditional.lstrip().rstrip()
        if val == "True":
            return True
        elif val == "False":
            return False
        else:
            raise errors.AnsibleError("unable to evaluate conditional: %s" %
                                      conditional)

    if not isinstance(conditional, basestring):
        return conditional

    try:
        conditional = conditional.replace("\n", "\\n")
        result = safe_eval(conditional)
        if result not in [True, False]:
            raise errors.AnsibleError(
                "Conditional expression must evaluate to True or False: %s" %
                conditional)
        return result

    except (NameError, SyntaxError):
        raise errors.AnsibleError("Could not evaluate the expression: (%s)" %
                                  conditional)
Example #45
0
def safe_eval(str, locals=None, include_exceptions=False, template_call=False):
    '''
    this is intended for allowing things like:
    with_items: a_list_variable
    where Jinja2 would return a string
    but we do not want to allow it to call functions (outside of Jinja2, where
    the env is constrained)
    '''
    # FIXME: is there a more native way to do this?

    if template_call:
        # for the debug module in Ansible, allow debug of the form foo.bar.baz versus Python dictionary form
        str = template.template(None, "{{ %s }}" % str, locals)

    def is_set(var):
        return not var.startswith("$") and not '{{' in var

    def is_unset(var):
        return var.startswith("$") or '{{' in var

    # do not allow method calls to modules
    if not isinstance(str, basestring):
        # already templated to a datastructure, perhaps?
        if include_exceptions:
            return (str, None)
        return str
    if re.search(r'\w\.\w+\(', str):
        if include_exceptions:
            return (str, None)
        return str
    # do not allow imports
    if re.search(r'import \w+', str):
        if include_exceptions:
            return (str, None)
        return str
    try:
        result = None
        if not locals:
            result = eval(str)
        else:
            result = eval(str, None, locals)
        if include_exceptions:
            return (result, None)
        else:
            return result
    except Exception, e:
        if include_exceptions:
            return (str, e)
        return str
Example #46
0
    def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs):
        ''' handler for file transfer operations '''

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))
        source  = options.get('src', None)
        dest    = options.get('dest', None)
        copy    = utils.boolean(options.get('copy', 'yes'))

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

        dest = os.path.expanduser(dest) # CCTODO: Fix path for Windows hosts.
        source = template.template(self.runner.basedir, os.path.expanduser(source), inject)
        if copy:
            if '_original_file' in inject:
                source = utils.path_dwim_relative(inject['_original_file'], 'files', source, self.runner.basedir)
            else:
                source = utils.path_dwim(self.runner.basedir, source)

        remote_md5 = self.runner._remote_md5(conn, tmp, dest)
        if remote_md5 != '3':
            result = dict(failed=True, msg="dest '%s' must be an existing dir" % dest)
            return ReturnData(conn=conn, result=result)

        if copy:
            # transfer the file to a remote tmp location
            tmp_src = tmp + 'source'
            conn.put_file(source, tmp_src)

        # handle diff mode client side
        # handle check mode client side
        # fix file permissions when the copy is done as a different user
        if copy:
            if self.runner.sudo and self.runner.sudo_user != 'root' or self.runner.su and self.runner.su_user != 'root':
                self.runner._remote_chmod(conn, 'a+r', tmp_src, tmp)
            # Build temporary module_args.
            new_module_args = dict(
                src=tmp_src,
                original_basename=os.path.basename(source),
            )
            module_args = utils.merge_module_args(module_args, new_module_args)
        else:
            module_args = "%s original_basename=%s" % (module_args, pipes.quote(os.path.basename(source)))
        return self.runner._execute_module(conn, tmp, 'unarchive', module_args, inject=inject, complex_args=complex_args)
Example #47
0
def get_inject_vars(self, host):

    host_variables = self.inventory.get_variables(
        host, vault_password=self.vault_pass)
    ansible_host = self.inventory.get_host(host)

    # Keep track of variables in the order they will be merged
    to_merge = [
        ('Default Variables', self.default_vars),
    ]

    # Group variables
    groups = ansible_host.get_groups()
    for group in sorted(groups, key=lambda g: g.depth):
        to_merge.append(
            ("Group Variables ({})".format(group.name), group.get_variables())
        )

    combined_cache = self.get_combined_cache()

    # use combined_cache and host_variables to template the module_vars
    # we update the inject variables with the data we're about to template
    # since some of the variables we'll be replacing may be contained there too
    module_vars_inject = combine_vars(
        host_variables, combined_cache.get(host, {}))
    module_vars_inject = combine_vars(
        self.module_vars, module_vars_inject)
    module_vars = template.template(
        self.basedir, self.module_vars, module_vars_inject)

    inject = {}
    to_merge.extend([
        ('Host Variables', ansible_host.vars),
        ('Setup Cache', self.setup_cache.get(host, {})),
        ('Play Variables', self.play_vars),
        ('Play File Variables', self.play_file_vars),
        ('Role Variables', self.role_vars),
        ('Module Variables', module_vars),
        ('Variables Cache', self.vars_cache.get(host, {})),
        ('Role Parameters', self.role_params),
        ('Extra Variables', self.extra_vars),
    ])
    for name, value in to_merge:
        old_inject = inject
        inject = combine_vars(inject, value)
        print name
        show_diff(old_inject, inject)

    return inject
Example #48
0
    def _flag_handler(self, play, handler_name, host):
        '''
        if a task has any notify elements, flag handlers for run
        at end of execution cycle for hosts that have indicated
        changes have been made
        '''

        found = False
        for x in play.handlers():
            if handler_name == template(play.basedir, x.name, x.module_vars):
                found = True
                self.callbacks.on_notify(host, x.name)
                x.notified_by.append(host)
        if not found:
            raise errors.AnsibleError("change handler (%s) is not defined" % handler_name)
Example #49
0
    def test_varReplace_var_complex_var(self):

        old_setting = C.DEFAULT_LEGACY_PLAYBOOK_VARIABLES
        C.DEFAULT_LEGACY_PLAYBOOK_VARIABLES = True

        vars = {
            'x': '$y',
            'y': {
                'foo': 'result',
            },
        }
        template = '${x.foo}'
        res = template2.template(None, template, vars)
        assert res == 'result'

        C.DEFAULT_LEGACY_PLAYBOOK_VARIABLES = old_setting
Example #50
0
    def _get_role_path(self, role):
        """
        Returns the path on disk to the directory containing
        the role directories like tasks, templates, etc. Also
        returns any variables that were included with the role
        """
        orig_path = template(self.basedir, role, self.vars)

        role_vars = {}
        if type(orig_path) == dict:
            # what, not a path?
            parsed_role = utils.role_yaml_parse(orig_path)
            role_name = parsed_role.get('role', parsed_role.get('name'))
            if role_name is None:
                raise errors.AnsibleError(
                    "expected a role name in dictionary: %s" % orig_path)
            role_vars = orig_path
        else:
            role_name = utils.role_spec_parse(orig_path)["name"]

        role_path = None

        possible_paths = [
            utils.path_dwim(self.basedir, os.path.join('roles', role_name)),
            utils.path_dwim(self.basedir, role_name)
        ]

        if C.DEFAULT_ROLES_PATH:
            search_locations = C.DEFAULT_ROLES_PATH.split(os.pathsep)
            for loc in search_locations:
                loc = os.path.expanduser(loc)
                possible_paths.append(utils.path_dwim(loc, role_name))

        for path_option in possible_paths:
            if os.path.isdir(path_option):
                role_path = path_option
                break

        if role_path is None:
            raise errors.AnsibleError("cannot find role in %s" %
                                      " or ".join(possible_paths))

        return (role_path, role_vars)
Example #51
0
    def run_handlers(self, play):
        on_hosts = play._play_hosts
        hosts_count = len(on_hosts)
        for task in play.tasks():
            if task.meta is not None:

                fired_names = {}
                for handler in play.handlers():
                    if len(handler.notified_by) > 0:
                        self.inventory.restrict_to(handler.notified_by)

                        # Resolve the variables first
                        handler_name = template(play.basedir, handler.name,
                                                handler.module_vars)
                        if handler_name not in fired_names:
                            self._run_task(play, handler, True)
                        # prevent duplicate handler includes from running more than once
                        fired_names[handler_name] = 1

                        host_list = self._trim_unavailable_hosts(
                            play._play_hosts)
                        if handler.any_errors_fatal and len(
                                host_list) < hosts_count:
                            play.max_fail_pct = 0
                        if (hosts_count - len(host_list)) > int(
                            (play.max_fail_pct) / 100.0 * hosts_count):
                            host_list = None
                        if not host_list and not play.force_handlers:
                            self.callbacks.on_no_hosts_remaining()
                            return False

                        self.inventory.lift_restriction()
                        new_list = handler.notified_by[:]
                        for host in handler.notified_by:
                            if host in on_hosts:
                                while host in new_list:
                                    new_list.remove(host)
                        handler.notified_by = new_list

                continue

        return True
Example #52
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        args = {}
        if complex_args:
            args.update(complex_args)

        # attempt to prevent confusing messages when the variable didn't interpolate
        module_args = module_args.replace("{{ ", "{{").replace(" }}", "}}")

        kv = utils.parse_kv(module_args)
        args.update(kv)

        if not 'msg' in args and not 'var' in args:
            args['msg'] = 'Hello world!'

        result = {}
        if 'msg' in args:
            if 'fail' in args and utils.boolean(args['fail']):
                result = dict(failed=True, msg=args['msg'])
            else:
                result = dict(msg=args['msg'])
        elif 'var' in args and not utils.LOOKUP_REGEX.search(args['var']):
            results = template.template(self.basedir,
                                        args['var'],
                                        inject,
                                        convert_bare=True)
            result[args['var']] = results

        # force flag to make debug output module always verbose
        result['verbose_always'] = True

        return ReturnData(conn=conn, result=result)
Example #53
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):

        if not module_args:
            result = dict(failed=True, msg="No source file given")
            return ReturnData(conn=conn, comm_ok=True, result=result)

        source = module_args
        source = template.template(self.runner.basedir, source, inject)

        if '_original_file' in inject:
            source = utils.path_dwim_relative(inject['_original_file'],
                                              'defaults', source,
                                              self.runner.basedir)
        else:
            source = utils.path_dwim(self.runner.basedir, source)

        if os.path.exists(source):
            data = utils.parse_yaml_from_file(
                source, vault_password=self.runner.vault_pass)
            if data and type(data) != dict:
                raise errors.AnsibleError(
                    "%s must be stored as a dictionary/hash" % source)
            elif data is None:
                data = {}
            inject['defaults'].update(data)
            return ReturnData(conn=conn, comm_ok=True, result={})
        else:
            result = dict(failed=True,
                          msg="Source file not found.",
                          file=source)
            return ReturnData(conn=conn, comm_ok=True, result=result)
Example #54
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        ''' run the pause action module '''

        # note: this module does not need to pay attention to the 'check'
        # flag, it always runs

        hosts = ', '.join(self.runner.host_set)
        args = {}
        if complex_args:
            args.update(complex_args)
        # extra template call unneeded?
        args.update(
            parse_kv(
                template.template(self.runner.basedir, module_args, inject)))

        # Are 'minutes' or 'seconds' keys that exist in 'args'?
        if 'minutes' in args or 'seconds' in args:
            try:
                if 'minutes' in args:
                    self.pause_type = 'minutes'
                    # The time() command operates in seconds so we need to
                    # recalculate for minutes=X values.
                    self.seconds = int(args['minutes']) * 60
                else:
                    self.pause_type = 'seconds'
                    self.seconds = int(args['seconds'])
                    self.duration_unit = 'seconds'
            except ValueError, e:
                raise ae("non-integer value given for prompt duration:\n%s" %
                         str(e))
Example #55
0
    def _update_vars_files_for_host(self, host):

        if type(self.vars_files) != list:
            self.vars_files = [ self.vars_files ]

        if host is not None:
            inject = {}
            inject.update(self.playbook.inventory.get_variables(host))
            inject.update(self.playbook.SETUP_CACHE[host])

        for filename in self.vars_files:

            if type(filename) == list:

                # loop over all filenames, loading the first one, and failing if # none found
                found = False
                sequence = []
                for real_filename in filename:
                    filename2 = template(self.basedir, real_filename, self.vars)
                    filename3 = filename2
                    if host is not None:
                        filename3 = template(self.basedir, filename2, inject)
                    filename4 = utils.path_dwim(self.basedir, filename3)
                    sequence.append(filename4)
                    if os.path.exists(filename4):
                        found = True
                        data = utils.parse_yaml_from_file(filename4)
                        if type(data) != dict:
                            raise errors.AnsibleError("%s must be stored as a dictionary/hash" % filename4)
                        if host is not None:
                            if self._has_vars_in(filename2) and not self._has_vars_in(filename3):
                                # this filename has variables in it that were fact specific
                                # so it needs to be loaded into the per host SETUP_CACHE
                                self.playbook.SETUP_CACHE[host].update(data)
                                self.playbook.callbacks.on_import_for_host(host, filename4)
                        elif not self._has_vars_in(filename4):
                            # found a non-host specific variable, load into vars and NOT
                            # the setup cache
                            self.vars.update(data)
                    elif host is not None:
                        self.playbook.callbacks.on_not_import_for_host(host, filename4)
                    if found:
                        break
                if not found and host is not None:
                    raise errors.AnsibleError(
                        "%s: FATAL, no files matched for vars_files import sequence: %s" % (host, sequence)
                    )

            else:
                # just one filename supplied, load it!

                filename2 = template(self.basedir, filename, self.vars)
                filename3 = filename2
                if host is not None:
                    filename3 = template(self.basedir, filename2, inject)
                filename4 = utils.path_dwim(self.basedir, filename3)
                if self._has_vars_in(filename4):
                    continue
                new_vars = utils.parse_yaml_from_file(filename4)
                if new_vars:
                    if type(new_vars) != dict:
                        raise errors.AnsibleError("%s must be stored as dictionary/hash: %s" % (filename4, type(new_vars)))
                    if host is not None and self._has_vars_in(filename2) and not self._has_vars_in(filename3):
                        # running a host specific pass and has host specific variables
                        # load into setup cache
                        self.playbook.SETUP_CACHE[host] = utils.combine_vars(
                            self.playbook.SETUP_CACHE[host], new_vars)
                        self.playbook.callbacks.on_import_for_host(host, filename4)
                    elif host is None:
                        # running a non-host specific pass and we can update the global vars instead
                        self.vars = utils.combine_vars(self.vars, new_vars)
Example #56
0
    def __init__(self, playbook, ds, basedir):
        ''' constructor loads from a play datastructure '''

        for x in ds.keys():
            if not x in Play.VALID_KEYS:
                raise errors.AnsibleError("%s is not a legal parameter in an Ansible Playbook" % x)

        # allow all playbook keys to be set by --extra-vars
        self.vars             = ds.get('vars', {})
        self.vars_prompt      = ds.get('vars_prompt', {})
        self.playbook         = playbook
        self.vars             = self._get_vars()
        self.basedir          = basedir
        self.roles            = ds.get('roles', None)
        self.tags             = ds.get('tags', None)

        if self.tags is None:
            self.tags = []
        elif type(self.tags) in [ str, unicode ]:
            self.tags = self.tags.split(",")
        elif type(self.tags) != list:
            self.tags = []

        # We first load the vars files from the datastructure
        # so we have the default variables to pass into the roles
        self.vars_files = ds.get('vars_files', [])
        if not isinstance(self.vars_files, list):
            raise errors.AnsibleError('vars_files must be a list')
        self._update_vars_files_for_host(None)

        # now we load the roles into the datastructure
        self.included_roles = []
        ds = self._load_roles(self.roles, ds)
        
        # and finally re-process the vars files as they may have
        # been updated by the included roles
        self.vars_files = ds.get('vars_files', [])
        if not isinstance(self.vars_files, list):
            raise errors.AnsibleError('vars_files must be a list')
        self._update_vars_files_for_host(None)

        # template everything to be efficient, but do not pre-mature template
        # tasks/handlers as they may have inventory scope overrides
        _tasks    = ds.pop('tasks', [])
        _handlers = ds.pop('handlers', [])
        ds = template(basedir, ds, self.vars)
        ds['tasks'] = _tasks
        ds['handlers'] = _handlers

        self._ds = ds

        hosts = ds.get('hosts')
        if hosts is None:
            raise errors.AnsibleError('hosts declaration is required')
        elif isinstance(hosts, list):
            hosts = ';'.join(hosts)
        self.serial           = int(ds.get('serial', 0))
        self.hosts            = hosts
        self.name             = ds.get('name', self.hosts)
        self._tasks           = ds.get('tasks', [])
        self._handlers        = ds.get('handlers', [])
        self.remote_user      = ds.get('remote_user', ds.get('user', self.playbook.remote_user))
        self.remote_port      = ds.get('port', self.playbook.remote_port)
        self.sudo             = ds.get('sudo', self.playbook.sudo)
        self.sudo_user        = ds.get('sudo_user', self.playbook.sudo_user)
        self.transport        = ds.get('connection', self.playbook.transport)
        self.gather_facts     = ds.get('gather_facts', None)
        self.remote_port      = self.remote_port
        self.any_errors_fatal = utils.boolean(ds.get('any_errors_fatal', 'false'))
        self.accelerate       = utils.boolean(ds.get('accelerate', 'false'))
        self.accelerate_port  = ds.get('accelerate_port', None)
        self.accelerate_ipv6  = ds.get('accelerate_ipv6', False)
        self.max_fail_pct     = int(ds.get('max_fail_percentage', 100))

        load_vars = {}
        load_vars['playbook_dir'] = self.basedir
        if self.playbook.inventory.basedir() is not None:
            load_vars['inventory_dir'] = self.playbook.inventory.basedir()

        self._tasks      = self._load_tasks(self._ds.get('tasks', []), load_vars)
        self._handlers   = self._load_tasks(self._ds.get('handlers', []), load_vars)


        if self.sudo_user != 'root':
            self.sudo = True
Example #57
0
    def _load_tasks(self, tasks, vars=None, default_vars=None, sudo_vars=None, additional_conditions=None, original_file=None, role_name=None):
        ''' handle task and handler include statements '''

        results = []
        if tasks is None:
            # support empty handler files, and the like.
            tasks = []
        if additional_conditions is None:
            additional_conditions = []
        if vars is None:
            vars = {}
        if default_vars is None:
            default_vars = {}
        if sudo_vars is None:
            sudo_vars = {}

        old_conditions = list(additional_conditions)

        for x in tasks:

            # prevent assigning the same conditions to each task on an include
            included_additional_conditions = list(old_conditions)

            if not isinstance(x, dict):
                raise errors.AnsibleError("expecting dict; got: %s" % x)

            # evaluate sudo vars for current and child tasks 
            included_sudo_vars = {}
            for k in ["sudo", "sudo_user"]:
                if k in x:
                    included_sudo_vars[k] = x[k]
                elif k in sudo_vars:
                    included_sudo_vars[k] = sudo_vars[k]
                    x[k] = sudo_vars[k]

            if 'meta' in x:
                if x['meta'] == 'flush_handlers':
                    results.append(Task(self,x))
                    continue

            task_vars = self.vars.copy()
            task_vars.update(vars)
            if original_file:
                task_vars['_original_file'] = original_file

            if 'include' in x:
                tokens = shlex.split(str(x['include']))
                items = ['']
                included_additional_conditions = list(additional_conditions)
                include_vars = {}
                for k in x:
                    if k.startswith("with_"):
                        utils.deprecated("include + with_items is an unsupported feature and has been undocumented for many releases because of this", "1.5")
                        plugin_name = k[5:]
                        if plugin_name not in utils.plugins.lookup_loader:
                            raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
                        terms = template(self.basedir, x[k], task_vars)
                        items = utils.plugins.lookup_loader.get(plugin_name, basedir=self.basedir, runner=None).run(terms, inject=task_vars)
                    elif k.startswith("when_"):
                        included_additional_conditions.insert(0, utils.compile_when_to_only_if("%s %s" % (k[5:], x[k])))
                    elif k == 'when':
                        if type(x[k]) is str:
                            included_additional_conditions.insert(0, utils.compile_when_to_only_if("jinja2_compare %s" % x[k]))
                        elif type(x[k]) is list:
                            for i in x[k]:
                                included_additional_conditions.insert(0, utils.compile_when_to_only_if("jinja2_compare %s" % i))
                    elif k in ("include", "vars", "default_vars", "only_if", "sudo", "sudo_user", "role_name"):
                        continue
                    else:
                        include_vars[k] = x[k]

                default_vars = x.get('default_vars', {})
                if not default_vars:
                    default_vars = self.default_vars
                else:
                    default_vars = utils.combine_vars(self.default_vars, default_vars)

                # append the vars defined with the include (from above) 
                # as well as the old-style 'vars' element. The old-style
                # vars are given higher precedence here (just in case)
                task_vars = utils.combine_vars(task_vars, include_vars)
                if 'vars' in x:
                    task_vars = utils.combine_vars(task_vars, x['vars'])

                if 'only_if' in x:
                    included_additional_conditions.append(x['only_if'])

                new_role = None
                if 'role_name' in x:
                    new_role = x['role_name']

                for item in items:
                    mv = task_vars.copy()
                    mv['item'] = item
                    for t in tokens[1:]:
                        (k,v) = t.split("=", 1)
                        mv[k] = template(self.basedir, v, mv)
                    dirname = self.basedir
                    if original_file:
                        dirname = os.path.dirname(original_file)
                    include_file = template(dirname, tokens[0], mv)
                    include_filename = utils.path_dwim(dirname, include_file)
                    data = utils.parse_yaml_from_file(include_filename)
                    if 'role_name' in x and data is not None:
                        for x in data:
                            if 'include' in x:
                                x['role_name'] = new_role
                    loaded = self._load_tasks(data, mv, default_vars, included_sudo_vars, list(included_additional_conditions), original_file=include_filename, role_name=new_role)
                    results += loaded
            elif type(x) == dict:
                task = Task(self,x,module_vars=task_vars,default_vars=default_vars,additional_conditions=list(additional_conditions),role_name=role_name)
                results.append(task)
            else:
                raise Exception("unexpected task type")

        for x in results:
            if self.tags is not None:
                x.tags.extend(self.tags)

        return results
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):

        try:

            args = {}
            if complex_args:
                args.update(complex_args)
            args.update(parse_kv(module_args))

            account_number = args["account_number"]
            region = args["region"]
            cloudtrail_bucket = args["cloudtrail_bucket"]

            envdict = {}
            if self.runner.environment:
                env = template.template(self.runner.basedir,
                                        self.runner.environment,
                                        inject,
                                        convert_bare=True)
                env = utils.safe_eval(env)

            if region == "us-east-1":
                other_regions = [
                    "us-west-1", "us-west-2", "eu-west-1", "us-east-2"
                ]
            elif region == "us-east-2":
                other_regions = [
                    "us-east-1", "us-west-1", "us-west-2", "eu-west-1"
                ]
            elif region == "us-west-1":
                other_regions = [
                    "us-east-1", "us-east-2", "us-west-2", "eu-west-1"
                ]
            elif region == "us-west-2":
                other_regions = [
                    "us-east-1", "us-east-2", "us-west-1", "eu-west-1"
                ]
            elif region == "eu-west-1":
                other_regions = [
                    "us-east-1", "us-east-2", "us-west-1", "us-west-2"
                ]
            else:
                raise SystemExit(1)  # unsupported region

            for connect_region in other_regions:

                cloudtrail_name = "Cloudtrail-%s-%s" % (account_number,
                                                        connect_region)

                try:
                    connection = cloudtrail.connect_to_region(
                        connect_region,
                        aws_access_key_id=env.get("AWS_ACCESS_KEY_ID"),
                        aws_secret_access_key=env.get("AWS_SECRET_ACCESS_KEY"),
                        security_token=env.get("AWS_SECURITY_TOKEN"))
                except Exception, e:
                    raise Exception

                try:
                    result = connection.update_trail(
                        cloudtrail_name,
                        cloudtrail_bucket,
                        include_global_service_events=False)
                    result = connection.start_logging(cloudtrail_name)
                except Exception, e:
                    result = connection.create_trail(
                        cloudtrail_name,
                        cloudtrail_bucket,
                        include_global_service_events=False)
                    result = connection.start_logging(cloudtrail_name)
Example #59
0
    def run(self,
            conn,
            tmp,
            module_name,
            module_args,
            inject,
            complex_args=None,
            **kwargs):
        ''' handler for template operations '''

        # note: since this module just calls the copy module, the --check mode support
        # can be implemented entirely over there

        if not self.runner.is_playbook:
            raise errors.AnsibleError(
                "in current versions of ansible, templates are only usable in playbooks"
            )

        # load up options
        options = {}
        if complex_args:
            options.update(complex_args)
        options.update(utils.parse_kv(module_args))

        source = options.get('src', None)
        dest = options.get('dest', None)

        if (source is None
                and 'first_available_file' not in inject) or dest is None:
            result = dict(failed=True, msg="src and dest are required")
            return ReturnData(conn=conn, comm_ok=False, result=result)

        # 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 inject:
            found = False
            for fn in self.runner.module_vars.get('first_available_file'):
                fn_orig = fn
                fnt = template.template(self.runner.basedir, fn, inject)
                fnd = utils.path_dwim(self.runner.basedir, fnt)
                if not os.path.exists(fnd) and '_original_file' in inject:
                    fnd = utils.path_dwim_relative(inject['_original_file'],
                                                   'templates',
                                                   fn_orig,
                                                   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:
            source = template.template(self.runner.basedir, source, inject)

            if '_original_file' in inject:
                source = utils.path_dwim_relative(inject['_original_file'],
                                                  'templates', source,
                                                  self.runner.basedir)
            else:
                source = utils.path_dwim(self.runner.basedir, source)

        if dest.endswith("/"):
            base = os.path.basename(source)
            dest = os.path.join(dest, base)

        # template the source data locally & get ready to transfer
        try:
            resultant = template.template_from_file(self.runner.basedir,
                                                    source, inject)
        except Exception, e:
            result = dict(failed=True, msg=str(e))
            return ReturnData(conn=conn, comm_ok=False, result=result)