| |
@@ -1,23 +1,130 @@
|
| |
#!/usr/bin/python3
|
| |
- import modulemd
|
| |
+
|
| |
+
|
| |
+ import argparse
|
| |
import sys
|
| |
|
| |
- def usage():
|
| |
- print("Usage: modlint <file>")
|
| |
- sys.exit()
|
| |
+ import requests
|
| |
+ from modulemd import ModuleMetadata
|
| |
+
|
| |
+
|
| |
+ class RpmContentError(ValueError):
|
| |
+ """Metadata contains invalid/nonexistent srpm or commit."""
|
| |
+
|
| |
+ #: Mapping of HTTP status codes to actual failure reasons.
|
| |
+ REASONS = {
|
| |
+ 400: 'Bad hash',
|
| |
+ 404: 'Nonexistent rpm',
|
| |
+ }
|
| |
+
|
| |
+ def __init__(self, package, commit, status_code):
|
| |
+ super().__init__(self, package, commit, status_code)
|
| |
+
|
| |
+ self.package = package
|
| |
+ self.commit = commit
|
| |
+ self.status_code = status_code
|
| |
+
|
| |
+ def __repr__(self):
|
| |
+ return 'RpmContentError({pkg!r}, {commit!r}, {status!r})'.format(
|
| |
+ pkg=self.package,
|
| |
+ commit=self.commit,
|
| |
+ status=self.status_code
|
| |
+ )
|
| |
+
|
| |
+ def __str__(self):
|
| |
+ return '{pkg} [{commit}]: {reason}'.format(
|
| |
+ pkg=self.package,
|
| |
+ commit=self.commit,
|
| |
+ reason=self.REASONS.get(self.status_code, 'Unknown error')
|
| |
+ )
|
| |
+
|
| |
+
|
| |
+ def verify_rpm_content(package, metadata, *, requests=requests):
|
| |
+ """Verify the existence of dist-git repo for described package.
|
| |
+
|
| |
+ Keyword arguments:
|
| |
+ package -- Name of the package to verify (key in
|
| |
+ modulemd packages)
|
| |
+ metadata -- Metadata associated with the package
|
| |
+ (value in modulemd packages)
|
| |
+
|
| |
+ requests -- Dependency injection of networking library.
|
| |
+
|
| |
+ Returns:
|
| |
+ None if the associated repo exists.
|
| |
+
|
| |
+ Raises:
|
| |
+ RpmContentError -- when the package (or commit) does not exist
|
| |
+ in dist-git.
|
| |
+ """
|
| |
+
|
| |
+ # TODO: Get URL from the metadata
|
| |
+ CGIT_URL_TEMPLATE = 'http://pkgs.fedoraproject.org/cgit/rpms/{name}.git/commit'
|
| |
+
|
| |
+ commit = metadata.get('commit', 'HEAD')
|
| |
+
|
| |
+ response = requests.head(
|
| |
+ CGIT_URL_TEMPLATE.format(name=package),
|
| |
+ params={'id': commit}
|
| |
+ )
|
| |
+
|
| |
+ if response.status_code != requests.codes.ok:
|
| |
+ raise RpmContentError(package, commit, response.status_code)
|
| |
+
|
| |
+
|
| |
+ def rpm_content(mmd):
|
| |
+ """Generate (package, metadata) pairs from module.
|
| |
+
|
| |
+ Keyword arguments:
|
| |
+ mmd -- ModuleMetadata to be inspected.
|
| |
+
|
| |
+ Yields:
|
| |
+ (package, metadata) from mmd, if any.
|
| |
+ """
|
| |
+
|
| |
+ try:
|
| |
+ packages = mmd.components.rpms.packages
|
| |
+ except AttributeError:
|
| |
+ # Module has no packages -- end generation with no output
|
| |
+ return None
|
| |
+
|
| |
+ yield from packages.items()
|
| |
+
|
| |
+
|
| |
+ if __name__ == '__main__':
|
| |
+ parser = argparse.ArgumentParser(description='Validate module metadata.')
|
| |
+
|
| |
+ # Positional arguments
|
| |
+ parser.add_argument('file', help='Input metadata file')
|
| |
+
|
| |
+ args = parser.parse_args()
|
| |
+
|
| |
+ metadata = ModuleMetadata()
|
| |
+ metadata_errors = TypeError, ValueError
|
| |
+ all_went_well = True
|
| |
|
| |
- if (len(sys.argv) != 2):
|
| |
- usage()
|
| |
+ try:
|
| |
+ metadata.load(args.file)
|
| |
+ except metadata_errors as invalid_input_metadata:
|
| |
+ message = 'ERROR: Invalid input: {!s}'.format(invalid_input_metadata)
|
| |
+ sys.exit(message)
|
| |
|
| |
- filename = sys.argv[1]
|
| |
- modulemd = modulemd.ModuleMetadata()
|
| |
+ try:
|
| |
+ metadata.validate()
|
| |
+ except metadata_errors as invalid_metadata_structure:
|
| |
+ all_went_well = False
|
| |
+ print('ERROR: Invalid structure:', str(invalid_metadata_structure),
|
| |
+ file=sys.stderr)
|
| |
|
| |
- try:
|
| |
- modulemd.load(filename)
|
| |
- modulemd.validate()
|
| |
- except Exception as e:
|
| |
- # raise
|
| |
- print("ERROR: ", str(e))
|
| |
- sys.exit()
|
| |
+ for package in rpm_content(metadata):
|
| |
+ try:
|
| |
+ verify_rpm_content(*package)
|
| |
+ except RpmContentError as invalid_rpm:
|
| |
+ all_went_well = False
|
| |
+ print('RPM CONTENT ERROR:', str(invalid_rpm),
|
| |
+ file=sys.stderr)
|
| |
|
| |
- print("Everything is OK!")
|
| |
+ if all_went_well:
|
| |
+ print('Everything OK')
|
| |
+ else:
|
| |
+ sys.exit(1)
|
| |
This is more request for comments/review than PR.
I have expanded the modlint script with dist-git sanity check. For each package in the content, the Fedora CGIT is checked for existence of that package (and if present, its commit).
RFC: