berth/validate.py

117 lines
4.0 KiB
Python

#!/usr/bin/python
#
# Ideally we would use jsonschema.validate but getting useful error
# output has been challenging. This can be revisited as needed.
import yaml
import sys
def validate_leaves(prefix, vm, l):
valid_leaves = [ ]
# first check to make sure we have what we think we should
for nd in l:
n = nd[0]
t = nd[1]
o = False
if len(nd)>2:
o = nd[2]
try:
if n not in vm.keys():
if o:
print "[W] Missing leaf:", prefix+n
else:
print "[E] Missing leaf:", prefix+n
continue
if type(vm[n]) != type(t):
print "[E] Wrong type for %s (got '%s' expected '%s')" % (prefix+n, type(vm[n]).__name__, type(t).__name__)
continue
except:
print "[W] Unable to validate leaf:", prefix+n
continue
valid_leaves.append(n)
if type(vm) == type(dict()):
# now look for things we don't know how to deal with
for n in vm.keys():
if n not in [ x[0] for x in l]:
print "[W] Unexpected leaf:", prefix+n
return valid_leaves
def validate_file(filename):
try:
yamlgen = list(yaml.safe_load_all(open(filename)))
except yaml.parser.ParserError:
print "[E] Invalid yaml"
return
if not yamlgen or not yamlgen[0]:
print "[E] File contains no valid yaml"
return
top = list(yamlgen)[0]
vmlist = top["vmlist"]
if not vmlist or not isinstance(vmlist, dict):
print "[E] No vmlist dict declared"
return
for name in vmlist:
vm = vmlist[name]
print "VM:", name
vl = validate_leaves("", vm, [ ("enabled",bool()), ("vmconfig",dict()), ("netconfig",dict()), ("cloudconfig",dict()) ] )
if "vmconfig" in vl:
# validate vmconfig
vmconfig = vm["vmconfig"]
vl2 = validate_leaves("vmconfig.", vmconfig, [ ("cpu",dict()), ("rootfs",dict()) ])
if "cpu" in vl2:
# validate vmconfig.cpu
cpu = vmconfig["cpu"]
vl3 = validate_leaves("vmconfig.cpu.", cpu, [ ("vcpu",int()), ("ram_mb",int()) ])
if "vcpus" in vl3:
vcpu = int(cpu["vcpus"])
if vcpu < 1 or vcpu > 8:
print "[W] vmconfig.cpu.vcpu has odd looking value:", vcpu
if "ram_mb" in vl3:
ram_mb = int(cpu["ram_mb"])
if ram_mb < 512 or ram_mb > 32768:
print "[W] vmconfig.cpu.ram_mb has odd looking value:", ram_mb
if "rootfs" in vl2:
# validate vmconfig.rootfs
rootfs = vmconfig["rootfs"]
vl3 = validate_leaves("vmconfig.rootfs.", rootfs, [ ("sourceurl",str()), ("localtarget",str()), ("pvc_size",str()), ("pvc_class",str(), True) ])
if "sourceurl" in vl3:
if not rootfs["sourceurl"].startswith("http"):
print "[W] vmconfig.rootfs.sourceurl has odd looking value:", rootfs["sourceurl"]
if "netconfig" in vl:
# validate netconfig
netconfig = vm["netconfig"]
vm2 = validate_leaves("netconfig.", netconfig, [ ("ports",dict()), ("readinessTcpProbe",int(), True) ])
# do more?
if "cloudconfig" in vl:
# validate cloudconfig
cloudconfig = vm["cloudconfig"]
vl2 = validate_leaves("cloudconfig.", cloudconfig, [ ("metadata",str()), ("userdata",str()) ])
# check things look sane
for yamlobj in [ "metadata", "userdata" ]:
if yamlobj in vl2:
try:
yaml.load(cloudconfig[yamlobj])
except:
print "[E] Bad yaml for vmconfig.cloudconfig.%s" % yamlobj
if __name__ == "__main__":
for fn in sys.argv[1:]:
print "Filename:", fn
validate_file(fn)
print