Exemplo n.º 1
0
    def matchyaml(self, file: Lintable) -> List[MatchError]:
        matches: List[MatchError] = []
        if not self.matchplay or str(file.base_kind) != 'text/yaml':
            return matches

        yaml = ansiblelint.utils.parse_yaml_linenumbers(file)
        # yaml returned can be an AnsibleUnicode (a string) when the yaml
        # file contains a single string. YAML spec allows this but we consider
        # this an fatal error.
        if isinstance(yaml, str):
            if yaml.startswith('$ANSIBLE_VAULT'):
                return []
            return [MatchError(filename=str(file.path), rule=LoadingFailureRule())]
        if not yaml:
            return matches

        if isinstance(yaml, dict):
            yaml = [yaml]

        yaml = ansiblelint.skip_utils.append_skipped_rules(yaml, file)

        for play in yaml:

            # Bug #849
            if play is None:
                continue

            if self.id in play.get('skipped_rules', ()):
                continue

            matches.extend(self.matchplay(file, play))

        return matches
Exemplo n.º 2
0
    def run(
        self, file: Lintable, tags: Set[str] = set(), skip_list: List[str] = []
    ) -> List[MatchError]:
        matches: List[MatchError] = list()

        if not file.path.is_dir():
            try:
                if file.content is not None:  # loads the file content
                    pass
            except IOError as e:
                return [
                    MatchError(
                        message=str(e),
                        filename=file,
                        rule=LoadingFailureRule(),
                        tag=e.__class__.__name__.lower(),
                    )
                ]

        for rule in self.rules:
            if (
                not tags
                or rule.has_dynamic_tags
                or not set(rule.tags).union([rule.id]).isdisjoint(tags)
            ):
                rule_definition = set(rule.tags)
                rule_definition.add(rule.id)
                if set(rule_definition).isdisjoint(skip_list):
                    matches.extend(rule.getmatches(file))

        # some rules can produce matches with tags that are inside our
        # skip_list, so we need to cleanse the matches
        matches = [m for m in matches if m.tag not in skip_list]

        return matches
Exemplo n.º 3
0
 def _emit_matches(self, files: List[Lintable]) -> Generator[MatchError, None, None]:
     visited: Set[Lintable] = set()
     while visited != self.lintables:
         for lintable in self.lintables - visited:
             try:
                 for child in ansiblelint.utils.find_children(lintable):
                     if self.is_excluded(str(child.path)):
                         continue
                     self.lintables.add(child)
                     files.append(child)
             except MatchError as e:
                 e.rule = LoadingFailureRule()
                 yield e
             except AttributeError:
                 yield MatchError(
                     filename=str(lintable.path), rule=LoadingFailureRule()
                 )
             visited.add(lintable)
Exemplo n.º 4
0
 def _emit_matches(self, files: List[Lintable]) -> Generator[MatchError, None, None]:
     visited: Set = set()
     while visited != self.playbooks:
         for arg in self.playbooks - visited:
             try:
                 for child in ansiblelint.utils.find_children(arg, self.playbook_dir):
                     if self.is_excluded(str(child.path)):
                         continue
                     self.playbooks.add(child)
                     files.append(child)
             except MatchError as e:
                 e.rule = LoadingFailureRule()
                 yield e
             visited.add(arg)
Exemplo n.º 5
0
    def matchyaml(self, file: Lintable) -> List[MatchError]:
        matches: List[MatchError] = []
        if not self.matchplay:
            return matches

        yaml = ansiblelint.utils.parse_yaml_linenumbers(
            file.content, file.path)
        # yaml returned can be an AnsibleUnicode (a string) when the yaml
        # file contains a single string. YAML spec allows this but we consider
        # this an fatal error.
        if isinstance(yaml, str):
            return [MatchError(filename=file.path, rule=LoadingFailureRule())]
        if not yaml:
            return matches

        if isinstance(yaml, dict):
            yaml = [yaml]

        yaml = ansiblelint.skip_utils.append_skipped_rules(
            yaml, file.content, file.kind)

        for play in yaml:

            # Bug #849
            if play is None:
                continue

            if self.id in play.get('skipped_rules', ()):
                continue

            result = self.matchplay(file, play)
            if not result:
                continue

            if isinstance(result, tuple):
                result = [result]

            if not isinstance(result, list):
                raise TypeError("{} is not a list".format(result))

            for section, message, *optional_linenumber in result:
                linenumber = self._matchplay_linenumber(
                    play, optional_linenumber)
                matches.append(
                    self.create_matcherror(message=message,
                                           linenumber=linenumber,
                                           details=str(section),
                                           filename=file.path))
        return matches
Exemplo n.º 6
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)
Exemplo n.º 7
0
def find_children(lintable: Lintable) -> List[Lintable]:  # noqa: C901
    if not lintable.path.exists():
        return []
    playbook_dir = str(lintable.path.parent)
    _set_collections_basedir(playbook_dir or os.path.abspath('.'))
    add_all_plugin_dirs(playbook_dir or '.')
    if lintable.kind == 'role':
        playbook_ds = AnsibleMapping({'roles': [{'role': str(lintable.path)}]})
    elif lintable.kind not in ("playbook", "tasks"):
        return []
    else:
        try:
            playbook_ds = parse_yaml_from_file(str(lintable.path))
        except AnsibleError as e:
            raise SystemExit(str(e))
    results = []
    basedir = os.path.dirname(str(lintable.path))
    # playbook_ds can be an AnsibleUnicode string, which we consider invalid
    if isinstance(playbook_ds, str):
        raise MatchError(filename=str(lintable.path),
                         rule=LoadingFailureRule())
    for item in _playbook_items(playbook_ds):
        # if lintable.kind not in ["playbook"]:
        #     continue
        for child in play_children(basedir, item, lintable.kind, playbook_dir):
            # We avoid processing parametrized children
            path_str = str(child.path)
            if "$" in path_str or "{{" in path_str:
                continue

            # Repair incorrect paths obtained when old syntax was used, like:
            # - include: simpletask.yml tags=nginx
            valid_tokens = list()
            for token in split_args(path_str):
                if '=' in token:
                    break
                valid_tokens.append(token)
            path = ' '.join(valid_tokens)
            if path != path_str:
                child.path = Path(path)
                child.name = child.path.name

            results.append(child)
    return results
Exemplo n.º 8
0
    def run(self, playbookfile, tags=set(), skip_list=frozenset()) -> List:
        text = ""
        matches: List = list()
        error: Optional[IOError] = None

        for i in range(3):
            try:
                with open(playbookfile['path'], mode='r',
                          encoding='utf-8') as f:
                    text = f.read()
                break
            except IOError as e:
                _logger.warning("Couldn't open %s - %s [try:%s]",
                                playbookfile['path'], e.strerror, i)
                error = e
                sleep(1)
                continue
        else:
            return [
                MatchError(message=str(error),
                           filename=playbookfile['path'],
                           rule=LoadingFailureRule())
            ]

        for rule in self.rules:
            if not tags or not set(rule.tags).union([rule.id
                                                     ]).isdisjoint(tags):
                rule_definition = set(rule.tags)
                rule_definition.add(rule.id)
                if set(rule_definition).isdisjoint(skip_list):
                    matches.extend(rule.matchlines(playbookfile, text))
                    matches.extend(rule.matchtasks(playbookfile, text))
                    matches.extend(
                        rule.matchyaml(
                            Lintable(playbookfile['path'],
                                     content=text,
                                     kind=playbookfile['type'])))

        # some rules can produce matches with tags that are inside our
        # skip_list, so we need to cleanse the matches
        matches = [m for m in matches if m.tag not in skip_list]

        return matches
Exemplo n.º 9
0
    def run(
        self, file: Lintable, tags=set(),
        skip_list=frozenset()) -> List[MatchError]:
        matches: List[MatchError] = list()
        error: Optional[IOError] = None

        for i in range(3):
            try:
                if file.content is not None:  # loads the file content
                    break
            except IOError as e:
                _logger.warning("Couldn't open %s - %s [try:%s]", file.path,
                                e.strerror, i)
                error = e
                sleep(1)
                continue
        else:
            return [
                MatchError(message=str(error),
                           filename=str(file.path),
                           rule=LoadingFailureRule())
            ]

        for rule in self.rules:
            if not tags or not set(rule.tags).union([rule.id
                                                     ]).isdisjoint(tags):
                rule_definition = set(rule.tags)
                rule_definition.add(rule.id)
                if set(rule_definition).isdisjoint(skip_list):
                    matches.extend(rule.matchlines(file))
                    matches.extend(rule.matchtasks(file))
                    matches.extend(rule.matchyaml(file))

        # some rules can produce matches with tags that are inside our
        # skip_list, so we need to cleanse the matches
        matches = [m for m in matches if m.tag not in skip_list]

        return matches