Created
October 23, 2015 16:01
-
-
Save crazed/0cae1dc0e2d95da0cf5f to your computer and use it in GitHub Desktop.
lint-ansible.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import os | |
import re | |
import sys | |
import ansible.errors | |
import ansible.utils.template | |
import ansiblelint | |
import ansiblelint.utils | |
import jinja2 | |
def log_warn(msg): | |
print "warning: %s" % msg | |
def log_error(msg): | |
print "error: %s" % msg | |
def lint_ansible(file_path): | |
rules = ansiblelint.RulesCollection() | |
playbooks = set([file_path]) | |
runner = ansiblelint.Runner(rules, playbooks, [], ['ANSIBLE0002' ,'ANSIBLE0003']) | |
errors = [] | |
try: | |
matches = runner.run() | |
except ansible.errors.AnsibleYAMLValidationFailed as e: | |
error_str = str(e) | |
m = re.match(r".*Note: The error may actually appear before this position: line (\d+), column (\d+).*", error_str, re.DOTALL) | |
line = m.group(1) | |
errors.append({ | |
'message': 'failed to validate yml file %s' % e, | |
'filename': file_path, | |
'linenumber': line, | |
}) | |
return errors | |
except IOError as e: | |
errors.append({ | |
'message': 'failed to include another yml file %s' % e, | |
'filename': file_path, | |
'linenumber': '0', | |
}) | |
return errors | |
except Exception as e: | |
errors.append({ | |
'message': 'unknown error happend %s' % e, | |
'filename': file_path, | |
'linenumber': '0', | |
}) | |
return errors | |
for match in matches: | |
errors.append({ | |
'message': match.message, | |
'filename': match.filename, | |
'linenumber': match.linenumber, | |
}) | |
return errors | |
def lint_jinja(file_path): | |
loader = jinja2.FileSystemLoader([os.path.dirname(file_path)]) | |
environment = jinja2.Environment(trim_blocks=True, loader=loader) | |
environment.filters.update(ansible.utils.template._get_filters()) | |
errors = [] | |
try: | |
data = file(file_path).read() | |
if type(data) == str: | |
data = unicode(data, 'utf-8') | |
environment.from_string(data).render(func=lambda:None) | |
except jinja2.exceptions.TemplateSyntaxError as e: | |
errors.append({ | |
'message': e.message, | |
'filename': file_path, | |
'linenumber': e.lineno, | |
}) | |
except (jinja2.exceptions.UndefinedError, TypeError) as e: | |
# Ignore undefined errors | |
pass | |
return errors | |
if __name__ == '__main__': | |
for path in sys.argv[1:]: | |
if not os.path.isfile(path): | |
continue | |
errors = None | |
if re.match(r"(.*/templates/.*|.*\.j2$)", path): | |
errors = lint_jinja(path) | |
elif re.match(r".*\.yml$", path): | |
errors = lint_ansible(path) | |
if errors is None: | |
continue | |
for error in errors: | |
message = "[{0}:{1}] {2}".format( | |
error['filename'], | |
error['linenumber'], | |
error['message']) | |
log_error(message) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment