grrr. validation errors, but i think it's how i'm modifying the thing

This commit is contained in:
brent s. 2018-05-26 08:40:21 -04:00
parent 9f74e97c45
commit ee653e81f6
5 changed files with 146 additions and 84 deletions

View File

@ -13,7 +13,7 @@
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="\w+:(/?/?)[^\s]+"/> <xs:pattern value="\w+:(/?/?)[^\s]+"/>
<xs:pattern value=".*\{variable%[A-Za-z0-9_]\}.*"/> <xs:pattern value=".*\{variable%[A-Za-z0-9_]\}.*"/>
<xs:pattern value=".*\{xpath%[A-Za-z0-9_/\(\)\.\*@\-]+\}.*"/> <xs:pattern value=".*\{xpath%[&quot;'A-Za-z0-9_/\(\)\.\*@\-\[\]=]+\}.*"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<!-- END t_btag_uri --> <!-- END t_btag_uri -->
@ -23,7 +23,7 @@
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="([a-z0-9._-]+){1,255}"/> <xs:pattern value="([a-z0-9._-]+){1,255}"/>
<xs:pattern value=".*\{variable%[A-Za-z0-9_]\}.*"/> <xs:pattern value=".*\{variable%[A-Za-z0-9_]\}.*"/>
<xs:pattern value=".*\{xpath%[A-Za-z0-9_/\(\)\.\*@\-]+\}.*"/> <xs:pattern value=".*\{xpath%[&quot;'A-Za-z0-9_/\(\)\.\*@\-\[\]=]+\}.*"/>
<!-- We don't allow (string)(regex) or (regex)(string) or (string)(regex)(string) or multiple regexes --> <!-- We don't allow (string)(regex) or (regex)(string) or (string)(regex)(string) or multiple regexes -->
<!-- because that's just... not feasible to manage from a parsing perspective. --> <!-- because that's just... not feasible to manage from a parsing perspective. -->
<xs:pattern value="\{regex%.+\}"/> <xs:pattern value="\{regex%.+\}"/>
@ -75,7 +75,7 @@
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="($[156]($rounds=[0-9]+)?$[a-zA-Z0-9./]{1,16}$?|auto|)"/> <xs:pattern value="($[156]($rounds=[0-9]+)?$[a-zA-Z0-9./]{1,16}$?|auto|)"/>
<xs:pattern value="\{variable%[A-Za-z0-9_]\}"/> <xs:pattern value="\{variable%[A-Za-z0-9_]\}"/>
<xs:pattern value="\{xpath%[A-Za-z0-9_\(\)\.\*\-/]+\}"/> <xs:pattern value="\{xpath%[&quot;'A-Za-z0-9_\(\)\.\*\-/\[\]=]+\}"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<!-- END t_pass_salt --> <!-- END t_pass_salt -->
@ -90,9 +90,9 @@
<!-- sha512: "[a-zA-Z0-9./]{86}" --> <!-- sha512: "[a-zA-Z0-9./]{86}" -->
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="xs:string"> <xs:extension base="xs:string">
<xs:attribute name="hash_algo" type="t_pass_hash_algo"/> <xs:attribute name="hash_algo" type="t_pass_hash_algo" use="optional"/>
<xs:attribute name="hashed" type="xs:boolean" use="required"/> <xs:attribute name="hashed" type="xs:boolean" use="required"/>
<xs:attribute name="salt" type="t_pass_salt"/> <xs:attribute name="salt" type="t_pass_salt" use="optional"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
@ -105,7 +105,7 @@
<xs:pattern value=""/> <xs:pattern value=""/>
<xs:pattern value="(.+)/([^/]+)"/> <xs:pattern value="(.+)/([^/]+)"/>
<xs:pattern value="((.+)/([^/]+))?\{variable%[A-Za-z0-9_]\}((.+)/([^/]+))?"/> <xs:pattern value="((.+)/([^/]+))?\{variable%[A-Za-z0-9_]\}((.+)/([^/]+))?"/>
<xs:pattern value="((.+)/([^/]+))?\{xpath%[A-Za-z0-9_\(\)\.\*\-/]+\}((.+)/([^/]+))?"/> <xs:pattern value="((.+)/([^/]+))?\{xpath%[&quot;'A-Za-z0-9_\(\)\.\*\-/\[\]=]+\}((.+)/([^/]+))?"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<!-- END t_path --> <!-- END t_path -->
@ -180,6 +180,8 @@
<!-- We can't validate an actual ISO-3166 ALPHA-2 code, but we can validate the format. --> <!-- We can't validate an actual ISO-3166 ALPHA-2 code, but we can validate the format. -->
<!-- TODO: maybe cron the generation of an external namespace? --> <!-- TODO: maybe cron the generation of an external namespace? -->
<xs:pattern value="[A-Z]{2}"/> <xs:pattern value="[A-Z]{2}"/>
<xs:pattern value=".*\{variable%[A-Za-z0-9_]\}.*"/>
<xs:pattern value=".*\{xpath%[&quot;'A-Za-z0-9_/\(\)\.\*@\-\[\]=]+\}.*"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
@ -234,7 +236,7 @@
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}$)"/> <xs:pattern value="[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}$)"/>
<xs:pattern value="\{variable%[A-Za-z0-9_]\}"/> <xs:pattern value="\{variable%[A-Za-z0-9_]\}"/>
<xs:pattern value="\{xpath%[A-Za-z0-9_\(\)\.\*\-/]+\}"/> <xs:pattern value="\{xpath%[&quot;'A-Za-z0-9_\(\)\.\*\-/\[\]=]+\}"/>
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<!-- END t_username --> <!-- END t_username -->
@ -244,7 +246,7 @@
<xs:element name="bdisk"> <xs:element name="bdisk">
<xs:complexType> <xs:complexType>
<!-- Should this be xs:sequence instead? --> <!-- Should this be xs:sequence instead? -->
<xs:choice> <xs:sequence>
<!-- BDISK/PROFILE --> <!-- BDISK/PROFILE -->
<xs:element name="profile" maxOccurs="unbounded" minOccurs="1"> <xs:element name="profile" maxOccurs="unbounded" minOccurs="1">
<xs:complexType> <xs:complexType>
@ -275,7 +277,7 @@
<!-- refer to the 2009 POSIX spec, "3.282 Portable Filename Character Set" --> <!-- refer to the 2009 POSIX spec, "3.282 Portable Filename Character Set" -->
<!-- http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_282 --> <!-- http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_282 -->
<!-- (We use this string to name some files.) --> <!-- (We use this string to name some files.) -->
<xs:pattern value="([a-z0-9._-]+){1,255}"/> <xs:pattern value="([A-Za-z0-9._-]+){1,255}"/>
<xs:pattern value="\{variable%[A-Za-z0-9_]\}"/> <xs:pattern value="\{variable%[A-Za-z0-9_]\}"/>
<xs:pattern value="\{xpath%[A-Za-z0-9_\(\)\.\*\-/]+\}"/> <xs:pattern value="\{xpath%[A-Za-z0-9_\(\)\.\*\-/]+\}"/>
</xs:restriction> </xs:restriction>
@ -306,14 +308,14 @@
<xs:all> <xs:all>
<!-- BDISK/PROFILE/META/DEV/AUTHOR --> <!-- BDISK/PROFILE/META/DEV/AUTHOR -->
<xs:element name="author" maxOccurs="1" minOccurs="1" <xs:element name="author" maxOccurs="1" minOccurs="1"
type="xs:string"/> type="xs:normalizedString"/>
<!-- END BDISK/PROFILE/META/DEV/AUTHOR --> <!-- END BDISK/PROFILE/META/DEV/AUTHOR -->
<!-- BDISK/PROFILE/META/DEV/EMAIL --> <!-- BDISK/PROFILE/META/DEV/EMAIL -->
<!-- The following does NOT WORK. Shame, really. --> <!-- The following does NOT WORK. Shame, really. -->
<!-- It seems to be an invalid pattern per my XSD validator (xmllint). --> <!-- It seems to be an invalid pattern per my XSD validator (xmllint). -->
<!--<xs:pattern value="([!#-&apos;*+/-9=?A-Z^-~-]+(\.[!#-&apos;*+/-9=?A-Z^-~-]+)*|&quot;([]!#-[^-~ \t]|(\\[\t -~]))+&quot;)@([!#-&apos;*+/-9=?A-Z^-~-]+(\.[!#-&apos;*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])"/>--> <!--<xs:pattern value="([!#-&apos;*+/-9=?A-Z^-~-]+(\.[!#-&apos;*+/-9=?A-Z^-~-]+)*|&quot;([]!#-[^-~ \t]|(\\[\t -~]))+&quot;)@([!#-&apos;*+/-9=?A-Z^-~-]+(\.[!#-&apos;*+/-9=?A-Z^-~-]+)*|\[[\t -Z^-~]*])"/>-->
<xs:element name="email" maxOccurs="1" minOccurs="1" <xs:element name="email" maxOccurs="1" minOccurs="1"
type="xs:string"/> type="xs:normalizedString"/>
<!-- END BDISK/PROFILE/META/DEV/EMAIL --> <!-- END BDISK/PROFILE/META/DEV/EMAIL -->
<!-- BDISK/PROFILE/META/DEV/WEBSITE --> <!-- BDISK/PROFILE/META/DEV/WEBSITE -->
<xs:element name="website" maxOccurs="1" minOccurs="1" <xs:element name="website" maxOccurs="1" minOccurs="1"
@ -327,11 +329,25 @@
<xs:element name="uri" maxOccurs="1" minOccurs="1" type="t_btag_uri"/> <xs:element name="uri" maxOccurs="1" minOccurs="1" type="t_btag_uri"/>
<!-- END BDISK/PROFILE/META/URI --> <!-- END BDISK/PROFILE/META/URI -->
<!-- BDISK/PROFILE/META/VER --> <!-- BDISK/PROFILE/META/VER -->
<xs:element name="ver" maxOccurs="1" minOccurs="1" type="xs:string"/> <xs:element name="ver" maxOccurs="1" minOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:normalizedString">
<!-- Like ../names/uxname, this is also used to name certain files so, POSIX portable filename. -->
<xs:pattern value="([A-Za-z0-9._-]+){1,255}"/>
<xs:pattern value="\{variable%[A-Za-z0-9_]\}"/>
<xs:pattern value="\{xpath%[A-Za-z0-9_\(\)\.\*\-/]+\}"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<!-- END BDISK/PROFILE/META/VER --> <!-- END BDISK/PROFILE/META/VER -->
<!-- BDISK/PROFILE/META/MAX_RECURSE --> <!-- BDISK/PROFILE/META/MAX_RECURSE -->
<xs:element name="max_recurse" maxOccurs="1" minOccurs="1" <xs:element name="max_recurse" maxOccurs="1" minOccurs="1">
type="xs:positiveInteger"/> <xs:simpleType>
<xs:restriction base="xs:positiveInteger">
<xs:maxExclusive value="1000"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<!-- END BDISK/PROFILE/META/MAX_RECURSE --> <!-- END BDISK/PROFILE/META/MAX_RECURSE -->
<!-- BDISK/PROFILE/META/REGEXES --> <!-- BDISK/PROFILE/META/REGEXES -->
<xs:element name="regexes" maxOccurs="1" minOccurs="0"> <xs:element name="regexes" maxOccurs="1" minOccurs="0">
@ -389,12 +405,20 @@
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>
<!-- BDISK/PROFILE/ACCOUNTS/USER/USERNAME --> <!-- BDISK/PROFILE/ACCOUNTS/USER/USERNAME -->
<xs:element name="username" type="t_username" minOccurs="1" <xs:element name="username" type="t_username" maxOccurs="1"
maxOccurs="1"/> minOccurs="1"/>
<!-- END BDISK/PROFILE/ACCOUNTS/USER/USERNAME --> <!-- END BDISK/PROFILE/ACCOUNTS/USER/USERNAME -->
<!-- BDISK/PROFILE/ACCOUNTS/USER/COMMENT --> <!-- BDISK/PROFILE/ACCOUNTS/USER/COMMENT -->
<xs:element name="comment" type="xs:string" maxOccurs="1" <!-- https://en.wikipedia.org/wiki/Gecos_field -->
minOccurs="0"/> <!-- Through experimentation, this *seems* to cap at 990 chars. -->
<xs:element name="comment" maxOccurs="1"
minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:normalizedString">
<xs:maxLength value="990"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<!-- END BDISK/PROFILE/ACCOUNTS/USER/COMMENT --> <!-- END BDISK/PROFILE/ACCOUNTS/USER/COMMENT -->
<!-- BDISK/PROFILE/ACCOUNTS/USER/PASSWORD --> <!-- BDISK/PROFILE/ACCOUNTS/USER/PASSWORD -->
<xs:element name="password" type="t_password" maxOccurs="1" <xs:element name="password" type="t_password" maxOccurs="1"
@ -439,8 +463,10 @@
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="t_remote_file"> <xs:extension base="t_remote_file">
<!-- There is NO way we can validate this, because it will vary based on the algorithms supported by the build host. --> <!-- There is NO way we can validate this, because it will vary based on the algorithms supported by the build host. -->
<xs:attribute name="hash_algo" type="xs:string" use="required"/> <xs:attribute name="hash_algo" type="xs:string"
<xs:attribute name="explicit" type="xs:boolean" use="required"/> use="required"/>
<xs:attribute name="explicit" type="xs:boolean"
use="required"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
@ -452,15 +478,17 @@
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="t_remote_file"> <xs:extension base="t_remote_file">
<!-- Required; otherwise there's no point using it. --> <!-- Required; otherwise there's no point using it. -->
<xs:attribute name="keys" type="t_gpg_keyid_list" use="required"/> <xs:attribute name="keys" type="t_gpg_keyid_list"
<xs:attribute name="keyserver" type="t_btag_uri"/> use="required"/>
<xs:attribute name="keyserver" type="t_btag_uri"
use="optional"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SOURCES/SOURCE/SIG--> <!-- END BDISK/PROFILE/SOURCES/SOURCE/SIG-->
</xs:all> </xs:all>
<xs:attribute name="arch"> <xs:attribute name="arch" use="required">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="(i686|x86(_64)?|32|64)"/> <xs:pattern value="(i686|x86(_64)?|32|64)"/>
@ -590,7 +618,7 @@
minOccurs="0"/> minOccurs="0"/>
<!-- END BDISK/PROFILE/GPG/KEY/COMMENT --> <!-- END BDISK/PROFILE/GPG/KEY/COMMENT -->
</xs:all> </xs:all>
<xs:attribute name="algo"> <xs:attribute name="algo" use="optional">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:enumeration value="rsa"/> <xs:enumeration value="rsa"/>
@ -600,9 +628,9 @@
</xs:attribute> </xs:attribute>
<!-- We COULD constrain this further, but it's conditional upon the algo type. So we'll do that in BDisk itself. --> <!-- We COULD constrain this further, but it's conditional upon the algo type. So we'll do that in BDisk itself. -->
<!-- But it may be possible? https://stackoverflow.com/a/39045446/733214 --> <!-- But it may be possible? https://stackoverflow.com/a/39045446/733214 -->
<xs:attribute name="keysize" type="xs:positiveInteger"/> <xs:attribute name="keysize" type="xs:positiveInteger" use="optional"/>
<!-- XSD doesn't have a datatype for Epoch vs. 0 (for no expire). --> <!-- XSD doesn't have a datatype for Epoch vs. 0 (for no expire). -->
<xs:attribute name="expire"> <xs:attribute name="expire" use="optional">
<xs:simpleType> <xs:simpleType>
<!--This is xs:integer instead of xs:positiveInteger because 0 will fail validation then. --> <!--This is xs:integer instead of xs:positiveInteger because 0 will fail validation then. -->
<xs:restriction base="xs:integer"> <xs:restriction base="xs:integer">
@ -614,10 +642,10 @@
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/GPG/KEY --> <!-- END BDISK/PROFILE/GPG/KEY -->
</xs:sequence> </xs:sequence>
<xs:attribute name="keyid" type="t_gpg_keyid"/> <xs:attribute name="keyid" type="t_gpg_keyid" use="required"/>
<xs:attribute name="publish" type="xs:boolean"/> <xs:attribute name="publish" type="xs:boolean" use="optional"/>
<xs:attribute name="prompt_passphrase" type="xs:boolean"/> <xs:attribute name="prompt_passphrase" type="xs:boolean" use="required"/>
<xs:attribute name="gnupghome"> <xs:attribute name="gnupghome" use="optional">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="(.+)/([^/]+)"/> <xs:pattern value="(.+)/([^/]+)"/>
@ -691,7 +719,7 @@
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/PKI/CLIENT --> <!-- END BDISK/PROFILE/PKI/CLIENT -->
</xs:sequence> </xs:sequence>
<xs:attribute name="overwrite" type="xs:boolean"/> <xs:attribute name="overwrite" type="xs:boolean" use="required"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/PKI --> <!-- END BDISK/PROFILE/PKI -->
@ -700,45 +728,45 @@
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>
<!-- BDISK/PROFILE/SYNC/IPXE --> <!-- BDISK/PROFILE/SYNC/IPXE -->
<xs:element name="ipxe"> <xs:element name="ipxe" maxOccurs="1" minOccurs="0">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="t_path"> <xs:extension base="t_path">
<xs:attribute name="enabled" type="xs:boolean"/> <xs:attribute name="enabled" type="xs:boolean" use="optional"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SYNC/IPXE --> <!-- END BDISK/PROFILE/SYNC/IPXE -->
<!-- BDISK/PROFILE/SYNC/TFTP --> <!-- BDISK/PROFILE/SYNC/TFTP -->
<xs:element name="tftp"> <xs:element name="tftp" maxOccurs="1" minOccurs="0">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="t_path"> <xs:extension base="t_path">
<xs:attribute name="enabled" type="xs:boolean"/> <xs:attribute name="enabled" type="xs:boolean" use="optional"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SYNC/TFTP --> <!-- END BDISK/PROFILE/SYNC/TFTP -->
<!-- BDISK/PROFILE/SYNC/ISO --> <!-- BDISK/PROFILE/SYNC/ISO -->
<xs:element name="iso"> <xs:element name="iso" maxOccurs="1" minOccurs="0">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="t_path"> <xs:extension base="t_path">
<xs:attribute name="enabled" type="xs:boolean"/> <xs:attribute name="enabled" type="xs:boolean" use="optional"/>
</xs:extension> </xs:extension>
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SYNC/ISO --> <!-- END BDISK/PROFILE/SYNC/ISO -->
<!-- BDISK/PROFILE/SYNC/GPG --> <!-- BDISK/PROFILE/SYNC/GPG -->
<xs:element name="gpg"> <xs:element name="gpg" maxOccurs="1" minOccurs="0">
<xs:complexType> <xs:complexType>
<xs:simpleContent> <xs:simpleContent>
<xs:extension base="t_path"> <xs:extension base="t_path">
<xs:attribute name="enabled" type="xs:boolean"/> <xs:attribute name="enabled" type="xs:boolean" use="optional"/>
<xs:attribute name="format"> <xs:attribute name="format" use="required">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:enumeration value="asc"/> <xs:enumeration value="asc"/>
@ -752,17 +780,19 @@
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SYNC/GPG --> <!-- END BDISK/PROFILE/SYNC/GPG -->
<!-- BDISK/PROFILE/SYNC/RSYNC --> <!-- BDISK/PROFILE/SYNC/RSYNC -->
<xs:element name="rsync"> <xs:element name="rsync" maxOccurs="1" minOccurs="1">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<!-- BDISK/PROFILE/SYNC/RSYNC/USER --> <!-- BDISK/PROFILE/SYNC/RSYNC/USER -->
<xs:element name="user" type="t_username"/> <xs:element name="user" type="t_username" maxOccurs="1"
minOccurs="1"/>
<!-- END BDISK/PROFILE/SYNC/RSYNC/USER --> <!-- END BDISK/PROFILE/SYNC/RSYNC/USER -->
<!-- BDISK/PROFILE/SYNC/RSYNC/HOST --> <!-- BDISK/PROFILE/SYNC/RSYNC/HOST -->
<xs:element name="host" type="t_net_loc"/> <xs:element name="host" type="t_net_loc" maxOccurs="1"
minOccurs="1"/>
<!-- END BDISK/PROFILE/SYNC/RSYNC/HOST --> <!-- END BDISK/PROFILE/SYNC/RSYNC/HOST -->
<!-- BDISK/PROFILE/SYNC/RSYNC/PORT --> <!-- BDISK/PROFILE/SYNC/RSYNC/PORT -->
<xs:element name="port"> <xs:element name="port" maxOccurs="1" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:positiveInteger"> <xs:restriction base="xs:positiveInteger">
<xs:minInclusive value="1"/> <xs:minInclusive value="1"/>
@ -773,14 +803,15 @@
<!-- END BDISK/PROFILE/SYNC/RSYNC/PORT --> <!-- END BDISK/PROFILE/SYNC/RSYNC/PORT -->
<xs:choice> <xs:choice>
<!-- BDISK/PROFILE/SYNC/RSYNC/PUBKEY --> <!-- BDISK/PROFILE/SYNC/RSYNC/PUBKEY -->
<xs:element name="pubkey" type="t_path"/> <xs:element name="pubkey" type="t_path" maxOccurs="1"
minOccurs="1"/>
<!-- END BDISK/PROFILE/SYNC/RSYNC/PUBKEY --> <!-- END BDISK/PROFILE/SYNC/RSYNC/PUBKEY -->
<!-- BDISK/PROFILE/SYNC/RSYNC/PUBKEY --> <!-- BDISK/PROFILE/SYNC/RSYNC/PUBKEY -->
<xs:element name="password"/> <xs:element name="password" maxOccurs="1" minOccurs="1"/>
<!-- END BDISK/PROFILE/SYNC/RSYNC/PUBKEY --> <!-- END BDISK/PROFILE/SYNC/RSYNC/PUBKEY -->
</xs:choice> </xs:choice>
</xs:sequence> </xs:sequence>
<xs:attribute name="enabled" type="xs:boolean"/> <xs:attribute name="enabled" type="xs:boolean" use="required"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SYNC/IPXE --> <!-- END BDISK/PROFILE/SYNC/IPXE -->
@ -789,9 +820,9 @@
</xs:element> </xs:element>
<!-- END BDISK/PROFILE/SYNC --> <!-- END BDISK/PROFILE/SYNC -->
</xs:all> </xs:all>
<xs:attribute name="id" type="xs:positiveInteger"/> <xs:attribute name="id" type="xs:positiveInteger" use="optional"/>
<xs:attribute name="name" type="xs:string"/> <xs:attribute name="name" type="xs:string" use="optional"/>
<xs:attribute name="uuid"> <xs:attribute name="uuid" use="optional">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern <xs:pattern
@ -802,7 +833,7 @@
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK/PROFILE --> <!-- END BDISK/PROFILE -->
</xs:choice> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<!-- END BDISK --> <!-- END BDISK -->

View File

@ -12,7 +12,8 @@ transform = utils.transform()
valid = utils.valid() valid = utils.valid()


class Conf(object): class Conf(object):
def __init__(self, cfg, profile = None, validate = False): def __init__(self, cfg, profile = None, validate_cfg = False,
xsd_file = None):
""" """
A configuration object. A configuration object.


@ -40,6 +41,9 @@ class Conf(object):
You can provide any combination of these You can provide any combination of these
(e.g. "profile={'id': 2, 'name' = 'some_profile'}"). (e.g. "profile={'id': 2, 'name' = 'some_profile'}").
""" """
if validate_cfg == 'pre':
# Validate before attempting any other operations
self.validate()
self.xml_suppl = utils.xml_supplicant(cfg, profile = profile) self.xml_suppl = utils.xml_supplicant(cfg, profile = profile)
self.xml = self.xml_suppl.xml self.xml = self.xml_suppl.xml
for e in self.xml_suppl.xml.iter(): for e in self.xml_suppl.xml.iter():
@ -48,12 +52,11 @@ class Conf(object):
with open('/tmp/parsed.xml', 'wb') as f: with open('/tmp/parsed.xml', 'wb') as f:
f.write(lxml.etree.tostring(self.xml_suppl.xml)) f.write(lxml.etree.tostring(self.xml_suppl.xml))
self.profile = self.xml_suppl.profile self.profile = self.xml_suppl.profile
self.xsd = None self.xsd = xsd_file
self.cfg = {} self.cfg = {}
#if validate: if validate_cfg:
#if not self.validate(): # Need to write the XSD # Validation post-substitution
# raise ValueError('The configuration did not pass XSD/schema ' self.validate()
# 'validation')


def get_pki_obj(self, pki, pki_type): def get_pki_obj(self, pki, pki_type):
elem = {} elem = {}
@ -99,7 +102,7 @@ class Conf(object):
_source_item['hash_algo'] = None _source_item['hash_algo'] = None
if item == 'sig': if item == 'sig':
if elem.get('keys', False): if elem.get('keys', False):
_keys = [i.strip() for i in elem.attrib['keys'].split(',')] _keys = [i.strip() for i in elem.attrib['keys'].split()]
_source_item['keys'] = _keys _source_item['keys'] = _keys
else: else:
_source_item['keys'] = [] _source_item['keys'] = []
@ -108,9 +111,9 @@ class Conf(object):
else: else:
_source_item['keyserver'] = None _source_item['keyserver'] = None
_item = elem.text _item = elem.text
_flags = elem.get('flags', []) _flags = elem.get('flags', '')
if _flags: if _flags:
for f in _flags.split(','): for f in _flags.split():
if f.strip().lower() == 'none': if f.strip().lower() == 'none':
continue continue
_source_item['flags'].append(f.strip().lower()) _source_item['flags'].append(f.strip().lower())
@ -129,10 +132,12 @@ class Conf(object):
return(_source_item) return(_source_item)


def get_xsd(self): def get_xsd(self):
path = os.path.join(os.path.dirname(__file__), if not self.xsd:
'bdisk.xsd') path = os.path.join(os.path.dirname(__file__), 'bdisk.xsd')
with open(path, 'r') as f: else:
xsd = f.read() path = os.path.abspath(os.path.expanduser(self.xsd))
with open(path, 'rb') as f:
xsd = lxml.etree.parse(f)
return(xsd) return(xsd)


def parse_accounts(self): def parse_accounts(self):
@ -302,5 +307,20 @@ class Conf(object):
return() return()


def validate(self): def validate(self):
self.xsd = etree.XMLSchema(self.get_xsd()) # TODO: perform further validations that we can't do in XSD.
return(self.xsd.validate(self.xml)) # TODO: FIX ME. ALWAYS RETURNS INVALID:
# lxml.etree.DocumentInvalid: Element 'bdisk': No matching global declaration available for the validation root.
xsd = self.get_xsd()
self.xsd = etree.XMLSchema(xsd)
# This would return a bool if it validates or not.
#self.xsd.validate(self.xml)
# We want to get a more detailed exception.
#xml = self.xml_suppl.return_full().getroottree()
xml = self.xml_suppl.return_full()
with open('/tmp/bdisk.xml', 'wb') as f:
f.write(etree.tostring(xml))
with open('/tmp/bdisk.xsd', 'wb') as f:
f.write(etree.tostring(xsd))
self.xsd.assertValid(xml)
#print(self.xsd.validate(xml))
return()

View File

@ -975,6 +975,16 @@ class xml_supplicant(object):
).format(element.text)) ).format(element.text))
return(path) return(path)


def return_full(self):
#nsmap = self.return_naked_ns()
local_xml = lxml.etree.Element('bdisk',
nsmap = self.orig_xml.nsmap,
attrib = self.orig_xml.attrib)
local_xml.text = '\n '
for elem in self.xml.xpath('/bdisk/profile'):
local_xml.append(copy.deepcopy(elem))
return(local_xml)

def return_naked_ns(self): def return_naked_ns(self):
# It's so stupid I have to do this. # It's so stupid I have to do this.
return(self.orig_xml.nsmap) return(self.orig_xml.nsmap)

View File

@ -4,6 +4,7 @@
<meta> <meta>
<names> <names>
<name>BDISK</name> <name>BDISK</name>
<!--<name>{xpath%../uxname/text()}</name>-->
<uxname>bdisk</uxname> <uxname>bdisk</uxname>
<!-- Just like with previous versions of BDisk, you can reference other values... <!-- Just like with previous versions of BDisk, you can reference other values...
but now with the neat benefits of XPath! Everything you could do in build.ini's and more. but now with the neat benefits of XPath! Everything you could do in build.ini's and more.
@ -56,16 +57,16 @@
<source arch="x86_64"> <source arch="x86_64">
<mirror>http://archlinux.mirror.domain.tld</mirror> <mirror>http://archlinux.mirror.domain.tld</mirror>
<rootpath>/iso/latest</rootpath> <rootpath>/iso/latest</rootpath>
<tarball flags="regex,latest">{regex%tarball_x86_64}</tarball> <tarball flags="regex latest">{regex%tarball_x86_64}</tarball>
<checksum hash_algo="sha1" explicit="false">sha1sums.txt</checksum> <checksum hash_algo="sha1" explicit="false" flags="latest">sha1sums.txt</checksum>
<sig keys="7F2D434B9741E8AC" keyserver="hkp://pool.sks-keyservers.net" flags="regex,latest">{regex%sig_x86_64}</sig> <sig keys="7F2D434B9741E8AC" keyserver="hkp://pool.sks-keyservers.net" flags="regex latest">{regex%sig_x86_64}</sig>
</source> </source>
<source arch="i686"> <source arch="i686">
<mirror>http://archlinux32.mirror.domain.tld</mirror> <mirror>http://archlinux32.mirror.domain.tld</mirror>
<rootpath>/iso/latest</rootpath> <rootpath>/iso/latest</rootpath>
<tarball flags="regex,latest">{regex%tarball_i686}</tarball> <tarball flags="regex latest">{regex%tarball_i686}</tarball>
<checksum hash_algo="sha512" explicit="true">cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e</checksum> <checksum hash_algo="sha512" explicit="true">cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e</checksum>
<sig keys="248BF41F9BDD61D41D060AE774EDA3C6B06D0506" keyserver="hkp://pool.sks-keyservers.net" flags="regex,latest">{regex%sig_i686}</sig> <sig keys="248BF41F9BDD61D41D060AE774EDA3C6B06D0506" keyserver="hkp://pool.sks-keyservers.net" flags="regex latest">{regex%sig_i686}</sig>
</source> </source>
</sources> </sources>
<build its_full_of_stars="true"> <build its_full_of_stars="true">
@ -89,7 +90,7 @@
<ipxe sign="true" iso="true"> <ipxe sign="true" iso="true">
<uri>{xpath%//meta/dev/website/text()}/ipxe</uri> <uri>{xpath%//meta/dev/website/text()}/ipxe</uri>
</ipxe> </ipxe>
<pki overwrite="no"> <pki overwrite="false">
<!-- http://ipxe.org/crypto --> <!-- http://ipxe.org/crypto -->
<ca> <ca>
<cert hash_algo="sha512">{xpath%../../../build/paths/pki/text()}/ca.crt</cert> <cert hash_algo="sha512">{xpath%../../../build/paths/pki/text()}/ca.crt</cert>
@ -125,7 +126,7 @@
<csr/> <csr/>
<key cipher="none" passphrase="none" keysize="4096">{xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key</key> <key cipher="none" passphrase="none" keysize="4096">{xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key</key>
<subject> <subject>
<commonName>some client name</commonName> <commonName>website.tld</commonName>
<countryName>XX</countryName> <countryName>XX</countryName>
<localityName>Some City</localityName> <localityName>Some City</localityName>
<stateOrProvinceName>Some State</stateOrProvinceName> <stateOrProvinceName>Some State</stateOrProvinceName>
@ -137,7 +138,7 @@
</pki> </pki>
<!-- If prompt_passphrase is "no" and passphrase attribute is not given for a gpg element, we will try to use a <!-- If prompt_passphrase is "no" and passphrase attribute is not given for a gpg element, we will try to use a
blank passphrase for all operations. --> blank passphrase for all operations. -->
<gpg keyid="none" gnupghome="none" publish="no" prompt_passphrase="no"> <gpg keyid="none" gnupghome="none" publish="false" prompt_passphrase="false">
<!-- The below is only used if we are generating a key (i.e. keyid="none"). --> <!-- The below is only used if we are generating a key (i.e. keyid="none"). -->
<key algo="rsa" keysize="4096" expire="0"> <key algo="rsa" keysize="4096" expire="0">
<name>{xpath%../../../meta/dev/author/text()}</name> <name>{xpath%../../../meta/dev/author/text()}</name>
@ -162,7 +163,7 @@
<profile name="alternate" id="2" uuid="2ed07c19-2071-4d66-8569-da40475ba716"> <profile name="alternate" id="2" uuid="2ed07c19-2071-4d66-8569-da40475ba716">
<meta> <meta>
<names> <names>
<name>AnotherCD</name> <name>ALTCD</name>
<uxname>bdisk_alt</uxname> <uxname>bdisk_alt</uxname>
<pname>{xpath%../name/text()}</pname> <pname>{xpath%../name/text()}</pname>
</names> </names>
@ -197,16 +198,16 @@
<source arch="x86_64"> <source arch="x86_64">
<mirror>http://archlinux.mirror.domain.tld</mirror> <mirror>http://archlinux.mirror.domain.tld</mirror>
<rootpath>/iso/latest</rootpath> <rootpath>/iso/latest</rootpath>
<tarball flags="regex,latest">{regex%tarball_x86_64}</tarball> <tarball flags="regex latest">{regex%tarball_x86_64}</tarball>
<checksum hash_algo="sha1" explicit="false">sha1sums.txt</checksum> <checksum hash_algo="sha1" explicit="false" flags="latest">sha1sums.txt</checksum>
<sig keys="7F2D434B9741E8AC" keyserver="hkp://pool.sks-keyservers.net" flags="regex,latest">{regex%sig_x86_64}</sig> <sig keys="7F2D434B9741E8AC" keyserver="hkp://pool.sks-keyservers.net" flags="regex latest">{regex%sig_x86_64}</sig>
</source> </source>
<source arch="i686"> <source arch="i686">
<mirror>http://archlinux32.mirror.domain.tld</mirror> <mirror>http://archlinux32.mirror.domain.tld</mirror>
<rootpath>/iso/latest</rootpath> <rootpath>/iso/latest</rootpath>
<tarball flags="regex,latest">{regex%tarball_i686}</tarball> <tarball flags="regex latest">{regex%tarball_i686}</tarball>
<checksum hash_algo="sha512" explicit="true">cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e</checksum> <checksum hash_algo="sha512" explicit="true">cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e</checksum>
<sig keys="248BF41F9BDD61D41D060AE774EDA3C6B06D0506" keyserver="hkp://pool.sks-keyservers.net" flags="regex,latest">{regex%sig_i686}</sig> <sig keys="248BF41F9BDD61D41D060AE774EDA3C6B06D0506" keyserver="hkp://pool.sks-keyservers.net" flags="regex latest">{regex%sig_i686}</sig>
</source> </source>
</sources> </sources>
<build its_full_of_stars="true"> <build its_full_of_stars="true">
@ -230,7 +231,7 @@
<ipxe sign="true" iso="true"> <ipxe sign="true" iso="true">
<uri>{xpath%//meta/dev/website/text()}/ipxe</uri> <uri>{xpath%//meta/dev/website/text()}/ipxe</uri>
</ipxe> </ipxe>
<pki overwrite="no"> <pki overwrite="false">
<ca> <ca>
<cert hash_algo="sha512">{xpath%../../../build/paths/pki/text()}/ca.crt</cert> <cert hash_algo="sha512">{xpath%../../../build/paths/pki/text()}/ca.crt</cert>
<csr/> <csr/>
@ -252,7 +253,7 @@
<csr/> <csr/>
<key cipher="none" passphrase="none" keysize="4096">{xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key</key> <key cipher="none" passphrase="none" keysize="4096">{xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key</key>
<subject> <subject>
<commonName>some client name</commonName> <commonName>website.tld</commonName>
<countryName>XX</countryName> <countryName>XX</countryName>
<localityName>Some City</localityName> <localityName>Some City</localityName>
<stateOrProvinceName>Some State</stateOrProvinceName> <stateOrProvinceName>Some State</stateOrProvinceName>
@ -262,7 +263,7 @@
</subject> </subject>
</client> </client>
</pki> </pki>
<gpg keyid="none" gnupghome="none" publish="no" prompt_passphrase="no"> <gpg keyid="none" gnupghome="none" publish="false" prompt_passphrase="false">
<key algo="rsa" keysize="4096" expire="0"> <key algo="rsa" keysize="4096" expire="0">
<name>{xpath%../../../meta/dev/author/text()}</name> <name>{xpath%../../../meta/dev/author/text()}</name>
<email>{xpath%../../../meta/dev/email/text()}</email> <email>{xpath%../../../meta/dev/email/text()}</email>

View File

@ -40,7 +40,7 @@ alt_profile.attrib['name'] = 'alternate'
alt_profile.attrib['id'] = '2' alt_profile.attrib['id'] = '2'
alt_profile.attrib['uuid'] = '2ed07c19-2071-4d66-8569-da40475ba716' alt_profile.attrib['uuid'] = '2ed07c19-2071-4d66-8569-da40475ba716'


meta_tags = {'name': 'AnotherCD', meta_tags = {'name': 'ALTCD',
'uxname': 'bdisk_alt', 'uxname': 'bdisk_alt',
'pname': '{xpath%../name/text()}', 'pname': '{xpath%../name/text()}',
'desc': 'Another rescue/restore live environment.', 'desc': 'Another rescue/restore live environment.',