Skip to content
Snippets Groups Projects
run_lint.py 2.38 KiB
Newer Older
import yaml
from argparse import ArgumentParser
import subprocess
from pathlib import Path
import re
import sys
import os
from collections import defaultdict
def parse_argument():
    parser = ArgumentParser("ansible lint runner with customized spec")
    parser.add_argument('--targets', type=str, nargs='*',
                        help="path to roles or playbook targets")
    parser.add_argument('--logdir', type=Path, default=Path( __file__ + '/../logdir').resolve(), nargs='?', help='log directory default to ./ansiblelint/logdir')

    args = parser.parse_args()
    args.logdir.mkdir(exist_ok=True)
    return args
def parse_rule_output(line):
    # (filepath, line, rule, severity, rule_desc)
    expression = '(.*\.yml):([0-9]+): \[(.*)\] \[(.*)\] (.*$)'
    matched = re.match(expression, line)
    # print(line)
    matched_groups = matched.groups()
    return matched_groups

def group_by(output, idx):
    res = defaultdict(list)
    for i in output:
        # print(i)
        res[i[idx]].append(i)
    return res
cmd_template = "ansible-lint --parseable-severity --nocolor "
outputs = defaultdict()
def main():
    exit_code = 0
    args = parse_argument()
    for item in args.logdir.iterdir():
        item.unlink()
    cmd = cmd_template
    if args.targets is not None:
        cmd += ' ' + ' '.join(args.targets)
    else:
        rolenames = [str(i.resolve())
                     for i in Path(__file__ + '/../../plays/roles').resolve().iterdir() if i.is_dir()]
        cmd += ' ' + ' '.join(rolenames)
        # print(cmd)
    logfile = args.logdir.joinpath('logfile')
    cmd += ' 2>&1 | tee {}'.format(str(logfile.resolve()))
    # print(cmd)
    output = subprocess.check_output(cmd, shell=True)
    print(output.decode())
    output = output.decode().splitlines()
    # print(output)
    output = [parse_rule_output(line) for line in output]

    # group by serverity
    output = group_by(output, 3)
    # print(output.keys())
    # print(output.keys())
    for k,v in output.items():
        # print(k, v)
        if (k=='VERY_HIGH') and len(v) != 0:
            exit_code = 1
        current_log = args.logdir.joinpath(k).resolve()

        with current_log.open(mode='w') as f:
            f.writelines(['filepath\tline\trule\tserverity\trule description\n'])
            f.writelines(['\t'.join(list(i)) + '\n' for i in v])
    sys.exit(exit_code)
    # return
if __name__ == "__main__":
    main()