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