Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package autoyast_xml_validator for
openSUSE:Factory checked in at 2021-07-14 23:58:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/autoyast_xml_validator (Old)
and /work/SRC/openSUSE:Factory/.autoyast_xml_validator.new.2625 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "autoyast_xml_validator"
Wed Jul 14 23:58:48 2021 rev:2 rq:906260 version:1.0.9+gite8164d1
Changes:
--------
---
/work/SRC/openSUSE:Factory/autoyast_xml_validator/autoyast_xml_validator.changes
2021-07-12 21:40:22.764041351 +0200
+++
/work/SRC/openSUSE:Factory/.autoyast_xml_validator.new.2625/autoyast_xml_validator.changes
2021-07-14 23:59:15.129397514 +0200
@@ -1,0 +2,14 @@
+Wed Jul 14 09:17:08 UTC 2021 - [email protected]
+
+- Update to version 1.0.9+gite8164d1:
+ * Fix line shift in -l/--list Parameter
+
+-------------------------------------------------------------------
+Wed Jul 14 09:04:40 UTC 2021 - [email protected]
+
+- Update to version 1.0.8+git5cfc5e4:
+ * Adopt README.md (and by that the manpage) to the lastest parmater and name
changes
+ * Rename validate-autoyastxml.py -> autoyast-xml-validate.py
+ * Restructure paramters and add --cobbler-profile param
+
+-------------------------------------------------------------------
Old:
----
autoyast_xml_validator-1.0.6+git920f29b.obscpio
New:
----
autoyast_xml_validator-1.0.9+gite8164d1.obscpio
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ autoyast_xml_validator.spec ++++++
--- /var/tmp/diff_new_pack.18D44I/_old 2021-07-14 23:59:15.837392331 +0200
+++ /var/tmp/diff_new_pack.18D44I/_new 2021-07-14 23:59:15.841392301 +0200
@@ -17,7 +17,7 @@
Name: autoyast_xml_validator
-Version: 1.0.6+git920f29b
+Version: 1.0.9+gite8164d1
Release: 0
Summary: Cross distribution and cross architecture autoyast XML syntax
checker
License: GPL-2.0-or-later
@@ -44,17 +44,16 @@
%setup -q
%build
-go-md2man -in README.md |gzip >validate-autoyastxml.1.gz
+go-md2man -in README.md |gzip >autoyast-xml-validate.1.gz
%install
-install -m 0755 -D validate-autoyastxml.py
%{buildroot}%{_bindir}/validate-autoyastxml
-install -m 0644 -D validate-autoyastxml.1.gz
%{buildroot}%{_mandir}/man1/validate-autoyastxml.1.gz
-
+install -m 0755 -D autoyast-xml-validate.py
%{buildroot}%{_bindir}/autoyast-xml-validate
+install -m 0644 -D autoyast-xml-validate.1.gz
%{buildroot}%{_mandir}/man1/autoyast-xml-validate.1.gz
%files
%doc README.md
%license LICENSE
-%{_bindir}/validate-autoyastxml
-%{_mandir}/man1/validate-autoyastxml*
+%{_bindir}/autoyast-xml-validate
+%{_mandir}/man1/autoyast-xml-validate*
%changelog
++++++ autoyast_xml_validator-1.0.6+git920f29b.obscpio ->
autoyast_xml_validator-1.0.9+gite8164d1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/autoyast_xml_validator-1.0.6+git920f29b/README.md
new/autoyast_xml_validator-1.0.9+gite8164d1/README.md
--- old/autoyast_xml_validator-1.0.6+git920f29b/README.md 2021-07-09
18:07:24.000000000 +0200
+++ new/autoyast_xml_validator-1.0.9+gite8164d1/README.md 2021-07-14
11:16:03.000000000 +0200
@@ -1,12 +1,13 @@
-# validate-autoyastxml 1 2021-07-06 GNU
+# autoyast-xml-validate 1 2021-07-06 GNU
## NAME
-validate-autoyastxml
+autoyast-xml-validate
## SYNOPSIS
-validate-autoyastxml (-u URL | -s SYSTEM -c COBBLER | -f FILE) [-p PROFILE |
-d DISTRO [ -a ARCH ] ] [-v] [-h] [--save]
+autoyast-xml-validate (-u URL | -s SYSTEM -c COBBLER | -f FILE) [-p PROFILE |
-d DISTRO [ -a ARCH ] ] [-v] [-h] [--save]
+autoyast-xml-validate (-u URL | -f FILE | -c COBBLER ( -s COBBLER_SYSTEM | -p
COBBLER_PROFILE ) | -l) [-r PROFILE_RNG] [-P PRODUCT] [-a ARCH] [--save] [-v]
## DESCRIPTION
@@ -27,17 +28,20 @@
-s SYSTEM, --system SYSTEM
Use autoyast XML from machine (default: False)
Needs --cobbler
+ -p PROFILE, --profile PROFILE
+ Use autoyast XML from cobbler profile (default: False)
+ Needs --cobbler
-c COBBLER, --cobbler COBBLER
Cobbler IP address
- Needs --system
+ Needs --system or --profile
LOCATE XML AUTOYAST DEFINITIONS (profile.rng):
(default: /usr/share/YaST2/schema/autoyast/rng/profile.rng)
- -p PROFILE, --profile PROFILE
- Path to RELAX NG schema to use to validate XML
- -d DISTRO, --distro DISTRO
+ -r PROFILE_RNG, --profile-rng PROFILE_RNG
+ Path to RELAX NG schema to use to validate XML
(profile.rng)
+ -P PRODUCT, --product PRODUCT
Distribution specific XML syntax to check against
This needs yast2-schemas package installed
(by default uses x86_64 installed architecture specific
@@ -47,6 +51,17 @@
Chose a different architecture XML definition
(default x86_64)
+ -l, --list
+ Show products and archs (to be used with -P [ -a ]
param)
+ of installed and available XML syntax definitions
+
+ --save
+ Always store retrieved XML file, not only in error
case.
+ Especially useful if autoyast.xml is retrieved via -u
URL
+ or cobbler parameters. The file can be further edited or
+ worked on, also if syntax check was successful.
+
+
-h, --help show this help message and exit
-v, --verbose Raise verbosity level
@@ -76,13 +91,13 @@
## EXAMPLES
-```validate-autoyastxml.py -f /tmp/autoyast.xml```
+```autoyast-xml-validate -f /tmp/autoyast.xml```
Local autoyast.xml check - Check against a local XML file
(using rng files from locally installed yast2-schema package)
-```validate-autoyastxml.py -c cobbler.arch.suse.de -m zinfandel-4.arch.suse.de
--save```
+```autoyast-xml-validate -c cobbler.arch.suse.de -m zinfandel-4.arch.suse.de
--save```
cobbler generated autoyast.xml check
Download and validate against a cobbler generated autoyast.xml
@@ -93,18 +108,18 @@
further debugging or development.
-```validate-autoyastxml.py -c cobbler.arch.suse.de -m zinfandel-4.arch.suse.de
-d sle-15-sp3 -a aarch64```
+```autoyast-xml-validate -c cobbler.arch.suse.de -m zinfandel-4.arch.suse.de
-d sle-15-sp3 -a aarch64```
cobbler generated autoyast.xml SLE 15 SP3 aarch64 check:
Download and validate against a cobbler generated autoyast.xml using SLE 15
SP3
aarch64 XML definitions
-```validate-autoyastxml.py -f /tmp/autoyast_xml_validator__di2jtqv -d
sle-15-sp3 -a ppc64le```
+```autoyast-xml-validate -f /tmp/autoyast_xml_validator__di2jtqv -d sle-15-sp3
-a ppc64le```
Validate (probably previously with --save param downloaded) autoyast file
against
sle-15-sp3/ppc64le XML syntax correctness.
-```validate-autoyastxml.py --list```
+```autoyast-xml-validate --list```
List all available distros and their XML (profile.rng) definitions found on
disk
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/autoyast_xml_validator-1.0.6+git920f29b/autoyast-xml-validate.py
new/autoyast_xml_validator-1.0.9+gite8164d1/autoyast-xml-validate.py
--- old/autoyast_xml_validator-1.0.6+git920f29b/autoyast-xml-validate.py
1970-01-01 01:00:00.000000000 +0100
+++ new/autoyast_xml_validator-1.0.9+gite8164d1/autoyast-xml-validate.py
2021-07-14 11:16:03.000000000 +0200
@@ -0,0 +1,334 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+
+# Copyright SUSE LCC 2021
+
+# Author: Martin Rey <[email protected]> 2021
+# Author: Thomas Renninger <[email protected]> 2021
+
+import argparse
+import logging
+import sys
+import os
+import glob
+import types
+import tempfile
+from logging.config import dictConfig
+from socket import getfqdn
+from subprocess import PIPE, Popen
+from urllib.request import urlopen
+
+# Global
+COBBLER_XML_S_URL = 'http://{0}/cblr/svc/op/autoinstall/system/{1}'
+COBBLER_XML_P_URL = 'http://{0}/cblr/svc/op/autoinstall/profile/{1}'
+PROFILE_GLOB = '/usr/share/YaST2/schema/autoyast/products/*'
+PROFILE_LOCATION =
'/usr/share/YaST2/schema/autoyast/products/{0}/{1}/profile.rng'
+
+#: The dictionary, used by :class:`logging.config.dictConfig`
+#: use it to setup your logging formatters, handlers, and loggers
+#: For details, see
+#
https://docs.python.org/3.4/library/logging.config.html#configuration-dictionary-schema
+DEFAULT_LOGGING_DICT = types.MappingProxyType(
+ {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'formatters': {
+ 'standard': {'format': '[%(levelname)s]: %(message)s'},
+ },
+ 'handlers': {
+ 'default': {
+ 'level': 'NOTSET',
+ 'formatter': 'standard',
+ 'class': 'logging.StreamHandler',
+ },
+ },
+ 'loggers': {
+ __name__: {
+ 'handlers': ['default'],
+ 'level': 'INFO',
+ 'propagate': True,
+ },
+ },
+ }
+)
+
+#: Map verbosity level (int) to log level
+LOGLEVELS = types.MappingProxyType({
+ None: logging.WARNING, # 0
+ 0: logging.WARNING,
+ 1: logging.INFO,
+ 2: logging.DEBUG,
+})
+
+#: Instantiate our logger
+log = logging.getLogger(__name__)
+
+
+def parse(cliargs=None):
+ """Parse the command line and return parsed results.
+
+ :param cliargs: Arguments to parse or None (=use sys.argv) (Default value
= None)
+ :returns: parsed CLI result
+ :rtype: class:`argparse.Namespace`
+
+ """
+ parser = argparse.ArgumentParser(description='Validate autoyast XML',
formatter_class=argparse.RawTextHelpFormatter)
+ parsergroup = parser.add_mutually_exclusive_group(required=True)
+ parsergroup.add_argument(
+ '-u',
+ '--url',
+ action='store',
+ default=False,
+ help='Use autoyast XML from URL'
+ )
+ parsergroup.add_argument(
+ '-f',
+ '--file',
+ action='store',
+ default=False,
+ help='Use autoyast XML from file'
+ )
+ parsergroup.add_argument(
+ '-s',
+ '--cobbler_system',
+ action='store',
+ default=False,
+ help='Use autoyast XML from cobbler system (cobbler system list)'
+ )
+ parsergroup.add_argument(
+ '-p',
+ '--cobbler_profile',
+ action='store',
+ default=False,
+ help='Use autoyast XML from cobbler profile (cobbler profile list)\n\n'
+ )
+ parsergroup.add_argument(
+ '-l', '--list', action='store_true', default=False,
+ help='Show products and archs (to be used with -P [ -a ] param)\nof
installed and available XML syntax definitions\n\n'
+ )
+
+ parser.add_argument(
+ '-r',
+ '--profile-rng',
+ action='store',
+ default='/usr/share/YaST2/schema/autoyast/rng/profile.rng',
+ help='Path to RELAX NG schema to use to validate XML\n(default:
%(default)s)\n\n',
+ required=False
+ )
+ parser.add_argument(
+ '-c',
+ '--cobbler',
+ action='store',
+ default='localhost',
+ help='Cobbler hostname or IP address (default: %(default)s)',
+ required=False,
+ )
+ parser.add_argument(
+ '-P',
+ '--product',
+ action='store',
+ default='',
+ help='Product to check/validate against, needs yast2-schemas package
(see --list option)',
+ required=False
+ )
+ parser.add_argument(
+ '-a',
+ '--arch',
+ action='store',
+ default='',
+ help='Architecture to check/validate against, needs yast2-schemas
package (default: x86_64)\n\n',
+ required=False
+ )
+ parser.add_argument(
+ '--save', action='store_true', default=False,
+ help='Always store retrieved XML file, not only in error case'
+ )
+ parser.add_argument(
+ '-v', '--verbose', action='count', help='Raise verbosity level \n-v
info, -vv debug e.g. to see URL from retrieved autoyast file'
+ )
+ args = parser.parse_args(cliargs)
+
+ # Setup logging and the log level according to the '-v' option
+ dictConfig(DEFAULT_LOGGING_DICT)
+ log.setLevel(LOGLEVELS.get(args.verbose, logging.DEBUG))
+ log.debug('CLI args: %s', args)
+
+ if args.arch and not args.product:
+ log.error("-a/--arch option needs a -P/--product option")
+ sys.exit(2)
+ if not args.arch:
+ # Need to set default here to check empty value above
+ args.arch = 'x86_64'
+ return args
+
+
+def get_content_from_url(url):
+ """Get content of a website and return it.
+
+ :param url: URL to get content from
+ :returns: content of URL
+ :rtype: bool
+
+ """
+ with urlopen(url) as xml_site:
+ site_content = xml_site.read().decode('utf-8')
+ return site_content
+
+def list_products():
+
+ product = {}
+ product_folders = glob.glob(PROFILE_GLOB)
+ print("\nList of supported distributions and architectures:\n")
+ print("Product")
+ print("[ Architectures, ]\n")
+ for f in product_folders:
+ archs = []
+ arch_folders = glob.glob("%s/*" % f)
+ for a in arch_folders:
+ archs.append(os.path.basename(a))
+ if archs:
+ print(os.path.basename(f))
+ print(archs)
+ print()
+ product[os.path.basename(f)] = archs
+
+def get_rng(args):
+ """Get profile.rng file location depending on CLI args.
+
+ :param args: arguments passed to CLI
+ :returns: autoyast XML
+ :rtype: str
+
+ """
+ profile_rng = None
+
+ if args.product:
+ profile_rng = PROFILE_LOCATION.format(args.product, args.arch)
+ else:
+ profile_rng = args.profile_rng
+ if not os.path.isfile(profile_rng):
+ raise IOError("Cannot locate %s" % profile_rng)
+ return profile_rng
+
+def get_xml(args):
+ """Get XML string from different sources, depending on CLI args.
+
+ :param args: arguments passed to CLI
+ :returns: autoyast XML
+ :rtype: str
+
+ """
+ xml = None
+
+ if args.url:
+ xml = get_content_from_url(args.url)
+ elif args.cobbler_system:
+ url = COBBLER_XML_S_URL.format(args.cobbler, args.cobbler_system)
+ log.info('Try to download XML content located at URL: %s', url)
+ xml = get_content_from_url(url)
+ elif args.cobbler_profile:
+ url = COBBLER_XML_P_URL.format(args.cobbler, args.cobbler_profile)
+ log.info('Try to download XML content located at URL: %s', url)
+ xml = get_content_from_url(url)
+ elif args.file:
+ with open(args.file) as xml_file:
+ xml = xml_file.read()
+ else:
+ log.error(
+ 'No autoyast.xml source specified. Use either -u, -f or -p and -s
options'
+ )
+ return xml.strip()
+
+
+def validate_xml(args, xml, profile_rng):
+ """Check xml for errors with xmllint.
+
+ :param args: arguments passed to CLI
+ :param xml: autoyast XML as string
+ :returns: returns: returns: return if autoyast XML validates
+ :rtype: bool
+
+ """
+ # check xml syntax with xmllint
+ success = True
+ log_delim = "---------------------------------------------------------"
+
+ command = ['xmllint', '--noout', '--relaxng', profile_rng, '/dev/stdin']
+ process = Popen(
+ command,
+ stdout=PIPE,
+ stderr=PIPE,
+ stdin=PIPE
+ )
+ stdout, stderr = process.communicate(input=xml.encode())
+ log.debug('xmllint return code: %d', process.returncode)
+ if process.returncode:
+ log.warning("xmllint output %s", log_delim)
+ log.warning('stderr: %s', str(stderr, encoding='utf-8'))
+ log.warning('stdout: %s', str(stdout, encoding='utf-8'))
+ log.warning("xmllint output %s", log_delim)
+ success = False
+
+ command = ['jing', profile_rng, '/dev/stdin']
+ # check RELAX NG schema with jing
+ process = Popen(
+ command,
+ stdout=PIPE,
+ stderr=PIPE,
+ stdin=PIPE,
+ )
+ stdout, stderr = process.communicate(input=xml.encode())
+ log.debug('jing return code: %d', process.returncode)
+ if process.returncode:
+ log.warning("jing output %s", log_delim)
+ log.warning('stderr: %s', str(stderr, encoding='utf-8'))
+ log.warning('stdout: %s', str(stdout, encoding='utf-8'))
+ log.warning("jing output %s", log_delim)
+ success = False
+
+ if success:
+ print("XML file successfully parsed - No errors found")
+
+ if not success or args.save:
+ temp = tempfile.NamedTemporaryFile(prefix="autoyast_xml_validator_",
delete=False)
+ temp.write(xml.encode())
+ temp.close()
+ if not success:
+ raise SyntaxError('XML has wrong Syntax. XML file store here: %s'
% temp.name)
+ else:
+ print("XML file stored: %s" % temp.name)
+
+ """
+ A returncode of 0 means "good". But the function should return True
+ if the XML is valid. As 0 is falsy in Python, bool(0) would return
+ False. Thus it is needed to invert the bool with a 'not' to adapt it
+ to our needs.
+ return True if both checks have a returncode of 0
+ """
+ return success
+
+
+if __name__ == '__main__':
+ RETURN_CODE = 0
+ args = parse()
+ try:
+ if args.list:
+ list_products()
+ else:
+ profile_rng = get_rng(args)
+ xml = get_xml(args)
+ if not validate_xml(args, xml, profile_rng):
+ RETURN_CODE = 99
+ except IOError as err:
+ log.error('IOError: %s', err)
+ RETURN_CODE = 3
+ except SyntaxError as err:
+ log.error('SyntaxError: %s', err)
+ RETURN_CODE = 2
+ except Exception:
+ log.exception("Unknown Error")
+ RETURN_CODE = 1
+
+ sys.exit(RETURN_CODE)
+
+# EOF
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/autoyast_xml_validator-1.0.6+git920f29b/validate-autoyastxml.py
new/autoyast_xml_validator-1.0.9+gite8164d1/validate-autoyastxml.py
--- old/autoyast_xml_validator-1.0.6+git920f29b/validate-autoyastxml.py
2021-07-09 18:07:24.000000000 +0200
+++ new/autoyast_xml_validator-1.0.9+gite8164d1/validate-autoyastxml.py
1970-01-01 01:00:00.000000000 +0100
@@ -1,334 +0,0 @@
-#!/usr/bin/python3
-# -*- coding: utf-8 -*-
-
-# Copyright SUSE LCC 2021
-
-# Author: Martin Rey <[email protected]> 2021
-# Author: Thomas Renninger <[email protected]> 2021
-
-import argparse
-import logging
-import sys
-import os
-import glob
-import types
-import tempfile
-from logging.config import dictConfig
-from socket import getfqdn
-from subprocess import PIPE, Popen
-from urllib.request import urlopen
-
-# Global
-COBBLER_XML_S_URL = 'http://{0}/cblr/svc/op/autoinstall/system/{1}'
-COBBLER_XML_P_URL = 'http://{0}/cblr/svc/op/autoinstall/profile/{1}'
-PROFILE_GLOB = '/usr/share/YaST2/schema/autoyast/products/*'
-PROFILE_LOCATION =
'/usr/share/YaST2/schema/autoyast/products/{0}/{1}/profile.rng'
-
-#: The dictionary, used by :class:`logging.config.dictConfig`
-#: use it to setup your logging formatters, handlers, and loggers
-#: For details, see
-#
https://docs.python.org/3.4/library/logging.config.html#configuration-dictionary-schema
-DEFAULT_LOGGING_DICT = types.MappingProxyType(
- {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'formatters': {
- 'standard': {'format': '[%(levelname)s]: %(message)s'},
- },
- 'handlers': {
- 'default': {
- 'level': 'NOTSET',
- 'formatter': 'standard',
- 'class': 'logging.StreamHandler',
- },
- },
- 'loggers': {
- __name__: {
- 'handlers': ['default'],
- 'level': 'INFO',
- 'propagate': True,
- },
- },
- }
-)
-
-#: Map verbosity level (int) to log level
-LOGLEVELS = types.MappingProxyType({
- None: logging.WARNING, # 0
- 0: logging.WARNING,
- 1: logging.INFO,
- 2: logging.DEBUG,
-})
-
-#: Instantiate our logger
-log = logging.getLogger(__name__)
-
-
-def parse(cliargs=None):
- """Parse the command line and return parsed results.
-
- :param cliargs: Arguments to parse or None (=use sys.argv) (Default value
= None)
- :returns: parsed CLI result
- :rtype: class:`argparse.Namespace`
-
- """
- parser = argparse.ArgumentParser(description='Validate autoyast XML',
formatter_class=argparse.RawTextHelpFormatter)
- parsergroup = parser.add_mutually_exclusive_group(required=True)
- parsergroup.add_argument(
- '-u',
- '--url',
- action='store',
- default=False,
- help='Use autoyast XML from URL'
- )
- parsergroup.add_argument(
- '-f',
- '--file',
- action='store',
- default=False,
- help='Use autoyast XML from file'
- )
- parsergroup.add_argument(
- '-s',
- '--cobbler_system',
- action='store',
- default=False,
- help='Use autoyast XML from cobbler system (cobbler system list)'
- )
- parsergroup.add_argument(
- '-p',
- '--cobbler_profile',
- action='store',
- default=False,
- help='Use autoyast XML from cobbler profile (cobbler profile list)\n\n'
- )
- parsergroup.add_argument(
- '-l', '--list', action='store_true', default=False,
- help='Show products and archs (to be used with -d [ -a ] param)\nof
installed and available XML syntax definitions\n\n'
- )
-
- parser.add_argument(
- '-r',
- '--profile-rng',
- action='store',
- default='/usr/share/YaST2/schema/autoyast/rng/profile.rng',
- help='Path to RELAX NG schema to use to validate XML\n(default:
%(default)s)\n\n',
- required=False,
- )
- parser.add_argument(
- '-c',
- '--cobbler',
- action='store',
- default='localhost',
- help='Cobbler hostname or IP address (default: %(default)s)',
- required=False,
- )
- parser.add_argument(
- '-P',
- '--product',
- action='store',
- default='',
- help='Product to check/validate against, needs yast2-schemas package
(see --list option)',
- required=False
- )
- parser.add_argument(
- '-a',
- '--arch',
- action='store',
- default='',
- help='Architecture to check/validate against, needs yast2-schemas
package (default: x86_64)\n\n',
- required=False
- )
- parser.add_argument(
- '--save', action='store_true', default=False,
- help='Always store retrieved XML file, not only in error case'
- )
- parser.add_argument(
- '-v', '--verbose', action='count', help='Raise verbosity level \n-v
info, -vv debug e.g. to see URL from retrieved autoyast file'
- )
- args = parser.parse_args(cliargs)
-
- # Setup logging and the log level according to the '-v' option
- dictConfig(DEFAULT_LOGGING_DICT)
- log.setLevel(LOGLEVELS.get(args.verbose, logging.DEBUG))
- log.debug('CLI args: %s', args)
-
- if args.arch and not args.product:
- log.error("-a/--arch option needs a -P/--product option")
- sys.exit(2)
- if not args.arch:
- # Need to set default here to check empty value above
- args.arch = 'x86_64'
- return args
-
-
-def get_content_from_url(url):
- """Get content of a website and return it.
-
- :param url: URL to get content from
- :returns: content of URL
- :rtype: bool
-
- """
- with urlopen(url) as xml_site:
- site_content = xml_site.read().decode('utf-8')
- return site_content
-
-def list_products():
-
- product = {}
- product_folders = glob.glob(PROFILE_GLOB)
- print("\nList of supported distributions and architectures:\n")
- print("Product")
- print("[ Architectures, ]\n")
- for f in product_folders:
- archs = []
- arch_folders = glob.glob("%s/*" % f)
- for a in arch_folders:
- archs.append(os.path.basename(a))
- if archs:
- print(os.path.basename(f))
- print(archs)
- print()
- product[os.path.basename(f)] = archs
-
-def get_rng(args):
- """Get profile.rng file location depending on CLI args.
-
- :param args: arguments passed to CLI
- :returns: autoyast XML
- :rtype: str
-
- """
- profile_rng = None
-
- if args.product:
- profile_rng = PROFILE_LOCATION.format(args.product, args.arch)
- else:
- profile_rng = args.profile_rng
- if not os.path.isfile(profile_rng):
- raise IOError("Cannot locate %s" % profile_rng)
- return profile_rng
-
-def get_xml(args):
- """Get XML string from different sources, depending on CLI args.
-
- :param args: arguments passed to CLI
- :returns: autoyast XML
- :rtype: str
-
- """
- xml = None
-
- if args.url:
- xml = get_content_from_url(args.url)
- elif args.cobbler_system:
- url = COBBLER_XML_S_URL.format(args.cobbler, args.cobbler_system)
- log.info('Try to download XML content located at URL: %s', url)
- xml = get_content_from_url(url)
- elif args.cobbler_profile:
- url = COBBLER_XML_P_URL.format(args.cobbler, args.cobbler_profile)
- log.info('Try to download XML content located at URL: %s', url)
- xml = get_content_from_url(url)
- elif args.file:
- with open(args.file) as xml_file:
- xml = xml_file.read()
- else:
- log.error(
- 'No autoyast.xml source specified. Use either -u, -f or -p and -s
options'
- )
- return xml.strip()
-
-
-def validate_xml(args, xml, profile_rng):
- """Check xml for errors with xmllint.
-
- :param args: arguments passed to CLI
- :param xml: autoyast XML as string
- :returns: returns: returns: return if autoyast XML validates
- :rtype: bool
-
- """
- # check xml syntax with xmllint
- success = True
- log_delim = "---------------------------------------------------------"
-
- command = ['xmllint', '--noout', '--relaxng', profile_rng, '/dev/stdin']
- process = Popen(
- command,
- stdout=PIPE,
- stderr=PIPE,
- stdin=PIPE
- )
- stdout, stderr = process.communicate(input=xml.encode())
- log.debug('xmllint return code: %d', process.returncode)
- if process.returncode:
- log.warning("xmllint output %s", log_delim)
- log.warning('stderr: %s', str(stderr, encoding='utf-8'))
- log.warning('stdout: %s', str(stdout, encoding='utf-8'))
- log.warning("xmllint output %s", log_delim)
- success = False
-
- command = ['jing', profile_rng, '/dev/stdin']
- # check RELAX NG schema with jing
- process = Popen(
- command,
- stdout=PIPE,
- stderr=PIPE,
- stdin=PIPE,
- )
- stdout, stderr = process.communicate(input=xml.encode())
- log.debug('jing return code: %d', process.returncode)
- if process.returncode:
- log.warning("jing output %s", log_delim)
- log.warning('stderr: %s', str(stderr, encoding='utf-8'))
- log.warning('stdout: %s', str(stdout, encoding='utf-8'))
- log.warning("jing output %s", log_delim)
- success = False
-
- if success:
- print("XML file successfully parsed - No errors found")
-
- if not success or args.save:
- temp = tempfile.NamedTemporaryFile(prefix="autoyast_xml_validator_",
delete=False)
- temp.write(xml.encode())
- temp.close()
- if not success:
- raise SyntaxError('XML has wrong Syntax. XML file store here: %s'
% temp.name)
- else:
- print("XML file stored: %s" % temp.name)
-
- """
- A returncode of 0 means "good". But the function should return True
- if the XML is valid. As 0 is falsy in Python, bool(0) would return
- False. Thus it is needed to invert the bool with a 'not' to adapt it
- to our needs.
- return True if both checks have a returncode of 0
- """
- return success
-
-
-if __name__ == '__main__':
- RETURN_CODE = 0
- args = parse()
- try:
- if args.list:
- list_products()
- else:
- profile_rng = get_rng(args)
- xml = get_xml(args)
- if not validate_xml(args, xml, profile_rng):
- RETURN_CODE = 99
- except IOError as err:
- log.error('IOError: %s', err)
- RETURN_CODE = 3
- except SyntaxError as err:
- log.error('SyntaxError: %s', err)
- RETURN_CODE = 2
- except Exception:
- log.exception("Unknown Error")
- RETURN_CODE = 1
-
- sys.exit(RETURN_CODE)
-
-# EOF
++++++ autoyast_xml_validator.obsinfo ++++++
--- /var/tmp/diff_new_pack.18D44I/_old 2021-07-14 23:59:15.965391394 +0200
+++ /var/tmp/diff_new_pack.18D44I/_new 2021-07-14 23:59:15.965391394 +0200
@@ -1,5 +1,5 @@
name: autoyast_xml_validator
-version: 1.0.6+git920f29b
-mtime: 1625846844
-commit: 920f29bd0e29481de94fd5e007777e564a1bb3c7
+version: 1.0.9+gite8164d1
+mtime: 1626254163
+commit: e8164d1ca540dbe046eb06c803cc3ff5b71de85d