Skip to content

Instantly share code, notes, and snippets.

@cro
Created April 18, 2017 15:39
Show Gist options
  • Save cro/ae956f1d4c7fe618812687d9dc1da7dc to your computer and use it in GitHub Desktop.
Save cro/ae956f1d4c7fe618812687d9dc1da7dc to your computer and use it in GitHub Desktop.
Git pre-commit script for git-pillar that validates content against a voluptuous schema.
#!/usr/bin/env python
# coding: utf-8
'''
Validate input file(s) against a Voluptuous schema
Pass a dash to read from stdin.
'''
from __future__ import print_function
import imp
import logging
import optparse
import sys
import yaml
try:
from salt.utils import voluptuous as V
except ImportError:
import voluptuous as V
try:
from logging import NullHandler
except ImportError:
class NullHandler(logging.Handler):
def emit(self, record): pass
logging.basicConfig(format='%(levelname)s %(asctime)s %(module)s: %(message)s')
log = logging.getLogger(__name__)
log.addHandler(NullHandler())
VERSION = '0.1.0'
def check(schema, infile):
data = yaml.safe_load(infile)
return schema(data)
def get_file_contents(args):
try:
idx = args.index('-')
except ValueError:
use_stdin = False
else:
use_stdin = True
args.pop(idx)
if not sys.stdin.isatty() or use_stdin:
stdin = sys.stdin.read()
if stdin:
yield stdin
for filename in args:
with open(filename, 'r') as f:
yield f.read()
def process(schema_file, file_args):
module = imp.load_source('module', schema_file)
schema = module.schema
for contents in get_file_contents(file_args):
check(schema, contents)
def main():
usage = 'Usage: %prog -s the_schema.py file1 file2'
parser = optparse.OptionParser(
usage=usage,
description=__doc__,
version=VERSION)
parser.add_option('-s', '--schema', dest='schema',
help='A schema to validate input file(s) against.')
parser.add_option('-v', dest='verbose', default=0, action='count',
help='Increment output verbosity; use multiple counts.')
opts, args = parser.parse_args()
log.addHandler(logging.StreamHandler())
log.setLevel(max(logging.ERROR - (opts.verbose * 10), 1))
if not opts.schema:
parser.error('Schema argument is required.')
if not args:
parser.error('No input files given.')
has_errors = True
try:
process(opts.schema, args)
except V.MultipleInvalid as exc:
for err in exc.errors:
print(err, file=sys.stderr)
except IOError as exc:
print(exc, file=sys.stderr)
except Exception:
log.debug('Unhandled exception', exc_info=True)
print('Unhandled exception. Run with -vvv flag.', file=sys.stderr)
else:
has_errors = False
return has_errors
if __name__ == '__main__':
raise SystemExit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment