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
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
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
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)
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