having a view function is stupid, and cleaning up some things with the validation... next up, actually creating the XML (and handle converting from JSON, but that'll be easy to parse since it should be in the same format as the dict)
This commit is contained in:
parent
c2e6fe1a04
commit
abaf931f37
@ -13,7 +13,6 @@ import errno
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
import getpass
|
import getpass
|
||||||
import os
|
import os
|
||||||
import pydoc # a dirty hack we use for pagination
|
|
||||||
import re
|
import re
|
||||||
import readline
|
import readline
|
||||||
import sys
|
import sys
|
||||||
@ -24,11 +23,6 @@ from ftplib import FTP_TLS
|
|||||||
|
|
||||||
xsd = 'https://aif.square-r00t.net/aif.xsd'
|
xsd = 'https://aif.square-r00t.net/aif.xsd'
|
||||||
|
|
||||||
# Before anything else... a disclaimer.
|
|
||||||
print('\nWARNING: This tool is not guaranteed to generate a working configuration file,\n' +
|
|
||||||
'\tbut for most basic cases it should work. I strongly encourage you to generate your own\n' +
|
|
||||||
'\tconfiguration file instead by reading the documentation: https://aif.square-r00t.net/#writing_an_xml_configuration_file\n\n')
|
|
||||||
|
|
||||||
# Ugh. You kids and your colors and bolds and crap.
|
# Ugh. You kids and your colors and bolds and crap.
|
||||||
class color(object):
|
class color(object):
|
||||||
PURPLE = '\033[95m'
|
PURPLE = '\033[95m'
|
||||||
@ -50,6 +44,7 @@ class aifgen(object):
|
|||||||
# Sanitize the user specification and find which protocol to use
|
# Sanitize the user specification and find which protocol to use
|
||||||
prefix = uri.split(':')[0].lower()
|
prefix = uri.split(':')[0].lower()
|
||||||
if uri.startswith('/'):
|
if uri.startswith('/'):
|
||||||
|
uri = 'file://{0}'.format(uri)
|
||||||
prefix = 'file'
|
prefix = 'file'
|
||||||
# Use the urllib module
|
# Use the urllib module
|
||||||
if prefix in ('http', 'https', 'file', 'ftp'):
|
if prefix in ('http', 'https', 'file', 'ftp'):
|
||||||
@ -92,14 +87,18 @@ class aifgen(object):
|
|||||||
return(data)
|
return(data)
|
||||||
|
|
||||||
def getXSD(self):
|
def getXSD(self):
|
||||||
xsdobj = etree.fromstring(self.webFetch(xsd).decode('utf-8'))
|
xsdobj = etree.fromstring(self.webFetch(xsd))
|
||||||
return(xsdobj)
|
return(xsdobj)
|
||||||
|
|
||||||
def getXML(self):
|
def getXML(self):
|
||||||
xmlobj = etree.fromstring(self.webFetch(self.args['cfgfile']).decode('utf-8'))
|
xmlobj = etree.fromstring(self.webFetch(self.args['cfgfile']))
|
||||||
return(xmlobj)
|
return(xmlobj)
|
||||||
|
|
||||||
def getOpts(self):
|
def getOpts(self):
|
||||||
|
# Before anything else... a disclaimer.
|
||||||
|
print('\nWARNING: This tool is not guaranteed to generate a working configuration file,\n' +
|
||||||
|
'\t but for most basic cases it should work. I strongly encourage you to generate your own\n' +
|
||||||
|
'\t configuration file instead by reading the documentation: https://aif.square-r00t.net/#writing_an_xml_configuration_file\n\n')
|
||||||
# This whole thing is ugly. Really, really ugly. Patches 100% welcome.
|
# This whole thing is ugly. Really, really ugly. Patches 100% welcome.
|
||||||
def chkPrompt(prompt, urls):
|
def chkPrompt(prompt, urls):
|
||||||
txtin = None
|
txtin = None
|
||||||
@ -704,14 +703,27 @@ class aifgen(object):
|
|||||||
return(conf)
|
return(conf)
|
||||||
|
|
||||||
def validateXML(self):
|
def validateXML(self):
|
||||||
pass
|
# First we validate the XSD.
|
||||||
|
if not lxml_avail:
|
||||||
|
exit('\nXML validation is only supported by LXML.\nIf you want to validate the XML, install the lxml python module (python-lxml) and try again.\n')
|
||||||
|
try:
|
||||||
|
xsd = etree.XMLSchema(self.getXSD())
|
||||||
|
print('\nXSD: {0}PASSED{1}'.format(color.BOLD, color.END))
|
||||||
|
except Exception as e:
|
||||||
|
exit('\nXSD: {0}FAILED{1}: {2}'.format(color.BOLD, color.END, e))
|
||||||
|
# Then we can validate the XML.
|
||||||
|
try:
|
||||||
|
xml = xsd.validate(self.getXML())
|
||||||
|
print('XML: {0}PASSED{1}\n'.format(color.BOLD, color.END))
|
||||||
|
except Exception as e:
|
||||||
|
print('XML: {0}FAILED{1}: {2}\n'.format(color.BOLD, color.END, e))
|
||||||
|
|
||||||
def main(self):
|
def main(self):
|
||||||
if self.args['oper'] == 'create':
|
if self.args['oper'] == 'create':
|
||||||
conf = self.getOpts()
|
conf = self.getOpts()
|
||||||
elif self.args['oper'] == 'convert':
|
elif self.args['oper'] == 'convert':
|
||||||
conf = self.convertJSON()
|
conf = self.convertJSON()
|
||||||
if self.args['oper'] in ('create', 'view', 'convert'):
|
if self.args['oper'] in ('create', 'convert'):
|
||||||
self.validateXML()
|
self.validateXML()
|
||||||
|
|
||||||
def parseArgs():
|
def parseArgs():
|
||||||
@ -722,7 +734,7 @@ def parseArgs():
|
|||||||
commonargs.add_argument('-f',
|
commonargs.add_argument('-f',
|
||||||
'--file',
|
'--file',
|
||||||
dest = 'cfgfile',
|
dest = 'cfgfile',
|
||||||
help = 'The file to create/validate/view. If not specified, defaults to ./aif.xml',
|
help = 'The file to create/validate. If not specified, defaults to ./aif.xml',
|
||||||
default = '{0}/aif.xml'.format(os.getcwd()))
|
default = '{0}/aif.xml'.format(os.getcwd()))
|
||||||
subparsers = args.add_subparsers(help = 'Operation to perform',
|
subparsers = args.add_subparsers(help = 'Operation to perform',
|
||||||
dest = 'oper')
|
dest = 'oper')
|
||||||
@ -732,9 +744,6 @@ def parseArgs():
|
|||||||
validateargs = subparsers.add_parser('validate',
|
validateargs = subparsers.add_parser('validate',
|
||||||
help = 'Validate an AIF-NG XML configuration file.',
|
help = 'Validate an AIF-NG XML configuration file.',
|
||||||
parents = [commonargs])
|
parents = [commonargs])
|
||||||
viewargs = subparsers.add_parser('view',
|
|
||||||
help = 'View an AIF-NG XML configuration file.',
|
|
||||||
parents = [commonargs])
|
|
||||||
convertargs = subparsers.add_parser('convert',
|
convertargs = subparsers.add_parser('convert',
|
||||||
help = 'Convert a "more" human-readable JSON configuration file to AIF-NG-compatible XML.',
|
help = 'Convert a "more" human-readable JSON configuration file to AIF-NG-compatible XML.',
|
||||||
parents = [commonargs])
|
parents = [commonargs])
|
||||||
@ -770,14 +779,6 @@ def verifyArgs(args):
|
|||||||
print('\nERROR: {0}: {1}'.format(e.strerror, e.filename))
|
print('\nERROR: {0}: {1}'.format(e.strerror, e.filename))
|
||||||
exit(('\nWe encountered an error when trying to use path {0}.\n' +
|
exit(('\nWe encountered an error when trying to use path {0}.\n' +
|
||||||
'Please review the output and address any issues present.').format(args['cfgfile']))
|
'Please review the output and address any issues present.').format(args['cfgfile']))
|
||||||
elif args['oper'] == 'view':
|
|
||||||
try:
|
|
||||||
with open(args['cfgfile'], 'r') as f:
|
|
||||||
f.read()
|
|
||||||
except OSError as e:
|
|
||||||
print('\nERROR: {0}: {1}'.format(e.strerror, e.filename))
|
|
||||||
exit(('\nWe encountered an error when trying to use path {0}.\n' +
|
|
||||||
'Please review the output and address any issues present.').format(args['cfgfile']))
|
|
||||||
if args['oper'] == 'convert':
|
if args['oper'] == 'convert':
|
||||||
# And we need to make sure we have read perms to the JSON input file.
|
# And we need to make sure we have read perms to the JSON input file.
|
||||||
try:
|
try:
|
||||||
@ -799,6 +800,8 @@ def main():
|
|||||||
aif = aifgen(verifyArgs(args))
|
aif = aifgen(verifyArgs(args))
|
||||||
if args['oper'] == 'create':
|
if args['oper'] == 'create':
|
||||||
aif.getOpts()
|
aif.getOpts()
|
||||||
|
if args['oper'] == 'validate':
|
||||||
|
aif.validateXML()
|
||||||
elif args['oper'] == 'convert':
|
elif args['oper'] == 'convert':
|
||||||
aif.convertJSON()
|
aif.convertJSON()
|
||||||
|
|
||||||
|
62
aifverify.py
62
aifverify.py
@ -1,62 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import io
|
|
||||||
from lxml import etree
|
|
||||||
from urllib.request import urlopen
|
|
||||||
|
|
||||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
|
|
||||||
# Validate in the form of file:XSD/namespace.
|
|
||||||
xmlfiles = {}
|
|
||||||
#xmlfiles['aif.xml'] = 'https://aif.square-r00t.net/aif.xsd'
|
|
||||||
xmlfiles['aif.xml'] = 'aif.xsd'
|
|
||||||
|
|
||||||
def validXSD(xsdfile):
|
|
||||||
print("Checking XSD: ", xsdfile)
|
|
||||||
webres = False
|
|
||||||
if re.match('^(https?|ftp)', xsdfile, re.IGNORECASE):
|
|
||||||
webres = True
|
|
||||||
if not webres:
|
|
||||||
with open('{0}/{1}'.format(cwd, xsdfile), 'rb') as f:
|
|
||||||
xsd_in = f.read()
|
|
||||||
else:
|
|
||||||
with urlopen(xsdfile) as f:
|
|
||||||
xsd_in = f.read()
|
|
||||||
xsd = False
|
|
||||||
try:
|
|
||||||
xsd_in = io.BytesIO(xsd_in)
|
|
||||||
xmlschema_doc = etree.parse(xsd_in)
|
|
||||||
xsd = etree.XMLSchema(xmlschema_doc)
|
|
||||||
except:
|
|
||||||
print('XSD: {0} failed.'.format(xsdfile))
|
|
||||||
return(xsd)
|
|
||||||
|
|
||||||
def validXML(xml, xsd):
|
|
||||||
print("Checking XML: ", xml)
|
|
||||||
xmlfile = xml
|
|
||||||
with open('{0}/{1}'.format(cwd, xml), 'rb') as f:
|
|
||||||
xml_in = f.read()
|
|
||||||
valid = False
|
|
||||||
try:
|
|
||||||
xml_in = io.BytesIO(xml_in)
|
|
||||||
xml = etree.parse(xml_in)
|
|
||||||
valid = xsd.validate(xml)
|
|
||||||
except:
|
|
||||||
print('XML: {0} failed.'.format(xmlfile))
|
|
||||||
return(valid)
|
|
||||||
|
|
||||||
def allValidXML(xmlfiles):
|
|
||||||
for key,value in xmlfiles.items():
|
|
||||||
xmlfile = key
|
|
||||||
xsdfile = xmlfiles[xmlfile]
|
|
||||||
xml = False
|
|
||||||
xsdobj = validXSD(xsdfile)
|
|
||||||
xml = validXML(xmlfile, xsdobj)
|
|
||||||
return(xml)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
allValidXML(xmlfiles)
|
|
Loading…
Reference in New Issue
Block a user