Skip to content

Instantly share code, notes, and snippets.

@crazed
Created October 23, 2015 16:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save crazed/0cae1dc0e2d95da0cf5f to your computer and use it in GitHub Desktop.
Save crazed/0cae1dc0e2d95da0cf5f to your computer and use it in GitHub Desktop.
lint-ansible.py
#!/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