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:
brent s 2017-05-13 08:11:59 -04:00
parent c2e6fe1a04
commit abaf931f37
2 changed files with 25 additions and 84 deletions

View File

@ -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()



View File

@ -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)