Пример #1
0
    def _resolve_action(self, action_name, mandatory=True):
        context = action_loader.find_plugin_with_context(action_name)
        if not context.resolved:
            context = module_loader.find_plugin_with_context(action_name)

        if context.resolved:
            return context.resolved_fqcn
        if mandatory:
            raise AnsibleParserError(
                "Could not resolve action %s in module_defaults" % action_name)
        display.vvvvv("Could not resolve action %s in module_defaults" %
                      action_name)
Пример #2
0
    def parse(self, skip_action_validation=False):
        '''
        Given a task in one of the supported forms, parses and returns
        returns the action, arguments, and delegate_to values for the
        task, dealing with all sorts of levels of fuzziness.
        '''

        thing = None

        action = None
        delegate_to = self._task_ds.get('delegate_to', Sentinel)
        args = dict()

        self.internal_redirect_list = []

        # This is the standard YAML form for command-type modules. We grab
        # the args and pass them in as additional arguments, which can/will
        # be overwritten via dict updates from the other arg sources below
        additional_args = self._task_ds.get('args', dict())

        # We can have one of action, local_action, or module specified
        # action
        if 'action' in self._task_ds:
            # an old school 'action' statement
            thing = self._task_ds['action']
            action, args = self._normalize_parameters(
                thing, action=action, additional_args=additional_args)

        # local_action
        if 'local_action' in self._task_ds:
            # local_action is similar but also implies a delegate_to
            if action is not None:
                raise AnsibleParserError(
                    "action and local_action are mutually exclusive",
                    obj=self._task_ds)
            thing = self._task_ds.get('local_action', '')
            delegate_to = 'localhost'
            action, args = self._normalize_parameters(
                thing, action=action, additional_args=additional_args)

        # module: <stuff> is the more new-style invocation

        # filter out task attributes so we're only querying unrecognized keys as actions/modules
        non_task_ds = dict(
            (k, v) for k, v in iteritems(self._task_ds)
            if (k not in self._task_attrs) and (not k.startswith('with_')))

        # walk the filtered input dictionary to see if we recognize a module name
        for item, value in iteritems(non_task_ds):
            context = None
            is_action_candidate = False
            if item in BUILTIN_TASKS:
                is_action_candidate = True
            elif skip_action_validation:
                is_action_candidate = True
            else:
                # If the plugin is resolved and redirected smuggle the list of candidate names via the task attribute 'internal_redirect_list'
                # TODO: remove self.internal_redirect_list (and Task._ansible_internal_redirect_list) once TE can use the resolved name for module_defaults
                context = action_loader.find_plugin_with_context(
                    item, collection_list=self._collection_list)
                if not context.resolved:
                    context = module_loader.find_plugin_with_context(
                        item, collection_list=self._collection_list)
                    if context.resolved and context.redirect_list:
                        self.internal_redirect_list = context.redirect_list
                elif context.redirect_list:
                    self.internal_redirect_list = context.redirect_list

                is_action_candidate = context.resolved and bool(
                    context.redirect_list)

            if is_action_candidate:
                # finding more than one module name is a problem
                if action is not None:
                    raise AnsibleParserError(
                        "conflicting action statements: %s, %s" %
                        (action, item),
                        obj=self._task_ds)

                if context is not None and context.resolved:
                    self.resolved_action = context.resolved_fqcn

                action = item
                thing = value
                action, args = self._normalize_parameters(
                    thing, action=action, additional_args=additional_args)

        # if we didn't see any module in the task at all, it's not a task really
        if action is None:
            if non_task_ds:  # there was one non-task action, but we couldn't find it
                bad_action = list(non_task_ds.keys())[0]
                raise AnsibleParserError(
                    "couldn't resolve module/action '{0}'. This often indicates a "
                    "misspelling, missing collection, or incorrect module path."
                    .format(bad_action),
                    obj=self._task_ds)
            else:
                raise AnsibleParserError("no module/action detected in task.",
                                         obj=self._task_ds)
        elif args.get('_raw_params',
                      '') != '' and action not in RAW_PARAM_MODULES:
            templar = Templar(loader=None)
            raw_params = args.pop('_raw_params')
            if templar.is_template(raw_params):
                args['_variable_params'] = raw_params
            else:
                raise AnsibleParserError(
                    "this task '%s' has extra params, which is only allowed in the following modules: %s"
                    % (action, ", ".join(RAW_PARAM_MODULES)),
                    obj=self._task_ds)

        return (action, args, delegate_to)