|
|
d4ef27 |
#!/usr/bin/python -tt
|
|
|
d4ef27 |
import argparse
|
|
|
d4ef27 |
import koji
|
|
|
d4ef27 |
import os
|
|
|
d4ef27 |
import re
|
|
|
d4ef27 |
import sys
|
|
|
d4ef27 |
import traceback
|
|
|
d4ef27 |
|
|
|
d4ef27 |
from collections import namedtuple
|
|
|
d4ef27 |
|
|
|
d4ef27 |
SigEntry = namedtuple('SigEntry', ['cbstag', 'localdir', 'remotedir', 'desturl'])
|
|
|
bf5efa |
KOJI_URL = 'https://cbs.centos.org/kojihub/'
|
|
|
d4ef27 |
WARNING = "WARNING: {0}: {1} {2}"
|
|
|
d4ef27 |
ERROR = "ERROR: {0}: {1} {2}"
|
|
|
d4ef27 |
TAGREGEX = r'(?P<signame>\w+)(?P<centosversion>\d)-(.*)-(?P<releasestage>candidate|testing|release)$'
|
|
|
d4ef27 |
MIRRORREGEX = r'(?P<centosversion>\d)/(?P<signame>\w+)/(?P<sigstructure>.*)'
|
|
|
d4ef27 |
|
|
|
d4ef27 |
|
|
|
d4ef27 |
def main(files=[]):
|
|
|
d4ef27 |
|
|
|
d4ef27 |
kojiclient = koji.ClientSession(KOJI_URL)
|
|
|
d4ef27 |
tags = [x.get('name') for x in kojiclient.listTags()]
|
|
|
d4ef27 |
|
|
|
d4ef27 |
for filename in files:
|
|
|
d4ef27 |
print '='*10 + ' Linting: {0} '.format(filename) + '='*10
|
|
|
d4ef27 |
with open(filename) as thefile:
|
|
|
d4ef27 |
lines = thefile.readlines()
|
|
|
d4ef27 |
|
|
|
d4ef27 |
for lineno,line in enumerate(map(str.strip, lines)):
|
|
|
d4ef27 |
if line.startswith('#'):
|
|
|
d4ef27 |
continue
|
|
|
d4ef27 |
se = SigEntry(*line.split('|'))
|
|
|
d4ef27 |
|
|
|
d4ef27 |
# Check that we put the right tags in the right list (testing -> buildlogs, release -> sign)
|
|
|
d4ef27 |
# and that the CentOS Version matches for all the URLs
|
|
|
d4ef27 |
try:
|
|
|
d4ef27 |
gs = re.match(TAGREGEX, se.cbstag.strip('/')).groupdict()
|
|
|
d4ef27 |
if gs['releasestage'] == 'release' and 'buildlogs' in filename:
|
|
|
d4ef27 |
msg = 'release tag in buildlogs list'
|
|
|
d4ef27 |
raise AssertionError
|
|
|
d4ef27 |
|
|
|
d4ef27 |
if gs['releasestage'] == 'testing' and 'sign' in filename:
|
|
|
d4ef27 |
msg = 'testing tag in sign list'
|
|
|
d4ef27 |
raise AssertionError
|
|
|
d4ef27 |
|
|
|
d4ef27 |
for attr in ['localdir','remotedir','desturl']:
|
|
Brian Stinson |
d19f46 |
match = re.match(MIRRORREGEX, se._asdict()[attr])
|
|
Brian Stinson |
d19f46 |
if not match:
|
|
Brian Stinson |
d19f46 |
msg = 'Malformed directory: {}\n {} does not match pattern: {}'.format(se._asdict()[attr], attr, MIRRORREGEX)
|
|
Brian Stinson |
d19f46 |
raise AssertionError
|
|
Brian Stinson |
d19f46 |
are = match.groupdict()
|
|
Brian Stinson |
d19f46 |
|
|
Brian Stinson |
d19f46 |
if are['centosversion'] != gs['centosversion']:
|
|
Brian Stinson |
d19f46 |
msg = 'version location of {0} does not match the CentOS Version of the CBS tag'.format(attr)
|
|
Brian Stinson |
d19f46 |
raise AssertionError
|
|
|
d4ef27 |
|
|
|
d4ef27 |
except AttributeError, e:
|
|
|
d4ef27 |
msg = 'bad cbs tag!'
|
|
|
d4ef27 |
print e
|
|
|
d4ef27 |
print(ERROR.format(filename+':'+str(lineno), se.cbstag.strip('/'), msg))
|
|
|
d4ef27 |
sys.exit(-1)
|
|
|
d4ef27 |
except AssertionError, e:
|
|
|
d4ef27 |
msg = msg or "Unkown error"
|
|
|
d4ef27 |
print(WARNING.format(filename+':'+str(lineno), se.cbstag.strip('/'), msg))
|
|
|
d4ef27 |
continue
|
|
|
d4ef27 |
|
|
|
d4ef27 |
# Check that we have trailing slashes for the path components so that RSYNC is happy
|
|
|
d4ef27 |
try:
|
|
|
d4ef27 |
for attr in ['cbstag','localdir','remotedir','desturl']:
|
|
|
d4ef27 |
assert(se._asdict()[attr].endswith('/'))
|
|
|
d4ef27 |
except AssertionError, e:
|
|
|
d4ef27 |
msg = '{} is missing trailing slash!'.format(attr)
|
|
|
d4ef27 |
print(WARNING.format(filename+':'+str(lineno), se.cbstag.strip('/'), msg))
|
|
|
d4ef27 |
continue
|
|
|
d4ef27 |
|
|
|
d4ef27 |
try:
|
|
|
d4ef27 |
assert(se.cbstag.strip('/') in tags)
|
|
|
d4ef27 |
except AssertionError, e:
|
|
|
d4ef27 |
print(ERROR.format(filename+':'+str(lineno), se.cbstag.strip('/'), 'CBS Tag does not exist!'))
|
|
|
d4ef27 |
sys.exit(-1)
|
|
|
d4ef27 |
|
|
|
d4ef27 |
# Check to be sure all the tags have RPMs in them
|
|
|
d4ef27 |
try:
|
|
|
d4ef27 |
builds = kojiclient.getLatestBuilds(se.cbstag.strip('/'))
|
|
|
d4ef27 |
assert(len(builds) > 0)
|
|
|
d4ef27 |
except AssertionError, e:
|
|
|
d4ef27 |
print(ERROR.format(str(lineno), se.cbstag.strip('/'), 'No RPMS in tag!'))
|
|
|
d4ef27 |
sys.exit(-1)
|
|
|
d4ef27 |
|
|
|
d4ef27 |
if __name__ == '__main__':
|
|
|
d4ef27 |
parser = argparse.ArgumentParser(description="Check the content control entries for sanity. If called without arguments, cclint will look in the current directory for any files named *_list")
|
|
|
d4ef27 |
|
|
|
d4ef27 |
parser.add_argument('files', metavar='content-control-file',
|
|
|
d4ef27 |
type=str, nargs="*", help="the file to check",
|
|
|
d4ef27 |
default=filter(lambda x: '_list' in x, os.listdir('.'))
|
|
|
d4ef27 |
)
|
|
|
d4ef27 |
|
|
|
d4ef27 |
args = parser.parse_args()
|
|
|
d4ef27 |
main(args.files)
|