2 changed files with 138 additions and 0 deletions
@ -0,0 +1,65 @@ |
|||||||
|
#! /usr/bin/env python |
||||||
|
""" Script to validate YAML file(s) against a YAML schema file """ |
||||||
|
|
||||||
|
from __future__ import print_function |
||||||
|
|
||||||
|
import argparse |
||||||
|
import os |
||||||
|
import sys |
||||||
|
|
||||||
|
try: |
||||||
|
import yaml |
||||||
|
except: |
||||||
|
print("Failed to import yaml.") |
||||||
|
print("You may need to install it with 'sudo pip install pyyaml'") |
||||||
|
print("") |
||||||
|
raise |
||||||
|
|
||||||
|
try: |
||||||
|
import cerberus |
||||||
|
except: |
||||||
|
print("Failed to import cerberus.") |
||||||
|
print("You may need to install it with 'sudo pip install cerberus'") |
||||||
|
print("") |
||||||
|
raise |
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Validate YAML file(s) against a schema') |
||||||
|
|
||||||
|
parser.add_argument('yaml_file', nargs='+', help='YAML config file(s)') |
||||||
|
parser.add_argument('--schema-file', type=str, action='store', |
||||||
|
help='YAML schema file', required=True) |
||||||
|
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', |
||||||
|
help='Verbose Output') |
||||||
|
|
||||||
|
args = parser.parse_args() |
||||||
|
schema_file = args.schema_file |
||||||
|
yaml_files = args.yaml_file |
||||||
|
verbose = args.verbose |
||||||
|
|
||||||
|
def load_yaml_file(file_name): |
||||||
|
with open(file_name, 'r') as stream: |
||||||
|
try: |
||||||
|
return yaml.load(stream) |
||||||
|
except yaml.YAMLError as exc: |
||||||
|
print(exc) |
||||||
|
raise |
||||||
|
|
||||||
|
# load the schema |
||||||
|
schema = load_yaml_file(schema_file) |
||||||
|
validator = cerberus.Validator(schema) |
||||||
|
|
||||||
|
# validate yaml files |
||||||
|
for yaml_file in yaml_files: |
||||||
|
if verbose: print("Validating {:}".format(yaml_file)) |
||||||
|
document = load_yaml_file(yaml_file) |
||||||
|
# ignore top-level entries prefixed with __ |
||||||
|
for key in document.keys(): |
||||||
|
if key.startswith('__'): del document[key] |
||||||
|
|
||||||
|
if not validator.validate(document): |
||||||
|
print("Validation Errors:") |
||||||
|
print(validator.errors) |
||||||
|
print("") |
||||||
|
raise Exception("Validation of {:} failed".format(yaml_file)) |
||||||
|
|
@ -0,0 +1,73 @@ |
|||||||
|
# Cerberus Validation Schema for module configuration files. |
||||||
|
# See http://docs.python-cerberus.org/en/stable/validation-rules.html |
||||||
|
|
||||||
|
|
||||||
|
module_name: |
||||||
|
# human-readable module name (used for descriptions, can contain spaces) |
||||||
|
type: string |
||||||
|
required: true |
||||||
|
|
||||||
|
serial_config: |
||||||
|
# UART configuration (optional) |
||||||
|
# A module can register autostart command(s) that are associated with a |
||||||
|
# configuration parameter, so that a user can select on which serial port to |
||||||
|
# run the command. |
||||||
|
# One or several commands can be defined. |
||||||
|
type: list |
||||||
|
minlength: 1 |
||||||
|
schema: |
||||||
|
type: dict |
||||||
|
schema: |
||||||
|
command: |
||||||
|
# script command that is executed on autostart. |
||||||
|
# These variables can be used: |
||||||
|
# ${SERIAL_DEV} Serial device (e.g. /dev/ttyS1) |
||||||
|
# ${BAUD_PARAM} param name for the baudrate |
||||||
|
# ${i} instance in [0, N-1] (for multi-instance commands) |
||||||
|
# It's possible to use multiple lines. |
||||||
|
type: string |
||||||
|
required: true |
||||||
|
|
||||||
|
port_config_param: |
||||||
|
# Parameter definition to configure on which port to run the |
||||||
|
# command |
||||||
|
type: dict |
||||||
|
required: true |
||||||
|
schema: |
||||||
|
name: |
||||||
|
# Parameter name (e.g. TEL_FRSKY_CONFIG, MAV_${i}_CONFIG) |
||||||
|
type: string |
||||||
|
regex: '[0-9A-Z_]+(\$\{i\}[0-9A-Z_]*)?' |
||||||
|
required: true |
||||||
|
group: |
||||||
|
# Associated parameter group (e.g. GPS) |
||||||
|
type: string |
||||||
|
required: true |
||||||
|
default: |
||||||
|
# Default value(s). This can be a string to specify the |
||||||
|
# serial tag (e.g. GPS1, TEL1, ...) or a list of strings |
||||||
|
# for multiple instances. |
||||||
|
# If omitted, the command is disabled by default. |
||||||
|
anyof: |
||||||
|
- type: string |
||||||
|
- type: list |
||||||
|
minlength: 1 |
||||||
|
schema: |
||||||
|
type: string |
||||||
|
label: |
||||||
|
# Optional command label (e.g. used in the autostart script). |
||||||
|
# If omitted, module_name is used. |
||||||
|
type: string |
||||||
|
num_instances: |
||||||
|
# Allow to configure and run multiple instances of a command. |
||||||
|
# For multiple instances, '${i}' can be used to refer to |
||||||
|
# an instance, for example in the parameter name or script |
||||||
|
# command. |
||||||
|
# Default: 1 |
||||||
|
type: integer |
||||||
|
min: 1 |
||||||
|
|
||||||
|
parameters: |
||||||
|
type: list |
||||||
|
# TODO |
||||||
|
|
Loading…
Reference in new issue