Beispiel #1
0
    def __init__(
            self,
            message: Optional[str] = None,
            linenumber: int = 0,
            column: Optional[int] = None,
            details: str = "",
            filename: Optional[str] = None,
            rule: BaseRule = RuntimeErrorRule(),
            tag: Optional[str] = None  # optional fine-graded tag
    ) -> None:
        """Initialize a MatchError instance."""
        super().__init__(message)

        if rule.__class__ is RuntimeErrorRule and not message:
            raise TypeError(
                f'{self.__class__.__name__}() missing a '
                "required argument: one of 'message' or 'rule'", )

        self.message = message or getattr(rule, 'shortdesc', "")
        self.linenumber = linenumber
        self.column = column
        self.details = details
        if filename:
            self.filename = normpath(filename)
        else:
            self.filename = os.getcwd()
        self.rule = rule
        self.ignored = False  # If set it will be displayed but not counted as failure
        # This can be used by rules that can report multiple errors type, so
        # we can still filter by them.
        self.tag = tag
Beispiel #2
0
    def _get_ansible_syntax_check_matches(lintable: Lintable) -> List[MatchError]:
        """Run ansible syntax check and return a list of MatchError(s)."""
        if lintable.kind != 'playbook':
            return []

        with timed_info("Executing syntax check on %s", lintable.path):
            cmd = ['ansible-playbook', '--syntax-check', str(lintable.path)]
            run = subprocess.run(
                cmd,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                shell=False,  # needed when command is a list
                universal_newlines=True,
                check=False
            )
            result = []
        if run.returncode != 0:
            message = None
            filename = str(lintable.path)
            linenumber = 0
            column = None

            stderr = strip_ansi_escape(run.stderr)
            stdout = strip_ansi_escape(run.stdout)
            if stderr:
                details = stderr
                if stdout:
                    details += "\n" + stdout
            else:
                details = stdout

            m = _ansible_syntax_check_re.search(stderr)
            if m:
                message = m.groupdict()['title']
                # Ansible returns absolute paths
                filename = m.groupdict()['filename']
                linenumber = int(m.groupdict()['line'])
                column = int(m.groupdict()['column'])

            if run.returncode == 4:
                rule: BaseRule = AnsibleSyntaxCheckRule()
            else:
                rule = RuntimeErrorRule()
                if not message:
                    message = (
                        f"Unexpected error code {run.returncode} from "
                        f"execution of: {' '.join(cmd)}")

            result.append(MatchError(
                message=message,
                filename=filename,
                linenumber=linenumber,
                column=column,
                rule=rule,
                details=details
                ))
        return result
Beispiel #3
0
def _taskshandlers_children(
    basedir: str, k: str, v: Union[None, Any], parent_type: FileType
) -> List[Lintable]:
    results: List[Lintable] = []
    if v is None:
        raise MatchError(
            message="A malformed block was encountered while loading a block.",
            rule=RuntimeErrorRule(),
        )
    for th in v:

        # ignore empty tasks, `-`
        if not th:
            continue

        with contextlib.suppress(LookupError):
            children = _get_task_handler_children_for_tasks_or_playbooks(
                th,
                basedir,
                k,
                parent_type,
            )
            results.append(children)
            continue

        if (
            'include_role' in th or 'import_role' in th
        ):  # lgtm [py/unreachable-statement]
            th = normalize_task_v2(th)
            _validate_task_handler_action_for_role(th['action'])
            results.extend(
                _roles_children(
                    basedir,
                    k,
                    [th['action'].get("name")],
                    parent_type,
                    main=th['action'].get('tasks_from', 'main'),
                )
            )
            continue

        if 'block' not in th:
            continue

        results.extend(_taskshandlers_children(basedir, k, th['block'], parent_type))
        if 'rescue' in th:
            results.extend(
                _taskshandlers_children(basedir, k, th['rescue'], parent_type)
            )
        if 'always' in th:
            results.extend(
                _taskshandlers_children(basedir, k, th['always'], parent_type)
            )

    return results
Beispiel #4
0
 def __init__(self, rulesdirs: Optional[List[str]] = None) -> None:
     """Initialize a RulesCollection instance."""
     if rulesdirs is None:
         rulesdirs = []
     self.rulesdirs = ansiblelint.file_utils.expand_paths_vars(rulesdirs)
     self.rules: List[BaseRule] = []
     # internal rules included in order to expose them for docs as they are
     # not directly loaded by our rule loader.
     self.rules.extend(
         [RuntimeErrorRule(), AnsibleParserErrorRule(), LoadingFailureRule()]
     )
     for rulesdir in self.rulesdirs:
         _logger.debug("Loading rules from %s", rulesdir)
         self.extend(load_plugins(rulesdir))
     self.rules = sorted(self.rules)
Beispiel #5
0
    def __init__(
            self,
            message: Optional[str] = None,
            # most linters report use (1,1) base, including yamllint and flake8
            # we should never report line 0 or column 0 in output.
            linenumber: int = 1,
            column: Optional[int] = None,
            details: str = "",
            filename: Optional[Union[str, Lintable]] = None,
            rule: BaseRule = RuntimeErrorRule(),
            tag: Optional[str] = None,  # optional fine-graded tag
    ) -> None:
        """Initialize a MatchError instance."""
        super().__init__(message)

        if rule.__class__ is RuntimeErrorRule and not message:
            raise TypeError(
                f'{self.__class__.__name__}() missing a '
                "required argument: one of 'message' or 'rule'", )

        self.message = message or getattr(rule, 'shortdesc', "")

        # Safety measture to ensure we do not endup with incorrect indexes
        if linenumber == 0:
            raise RuntimeError(
                "MatchError called incorrectly as line numbers start with 1")
        if column == 0:
            raise RuntimeError(
                "MatchError called incorrectly as column numbers start with 1")

        self.linenumber = linenumber
        self.column = column
        self.details = details
        self.filename = ""
        if filename:
            if isinstance(filename, Lintable):
                self.filename = normpath(str(filename.path))
            else:
                self.filename = normpath(filename)
        self.rule = rule
        self.ignored = False  # If set it will be displayed but not counted as failure
        # This can be used by rules that can report multiple errors type, so
        # we can still filter by them.
        self.tag = tag