#!/usr/bin/python # check-tags : a script to check koji tags of current builds to verify # correctness # # Copyright 2011, Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Author: Tim Flink import koji import fedora.client import datetime user = '' password = '' stale_tags = ['dist-f15-updates-testing-pending', 'dist-f15-updates-pending', 'dist-f15-updates-testing-candidate'] good_tags = ['dist-f15', 'dist-f15-updates-candidate'] rel = 'F15' bodhi_limit = 10 #bodhi_limit = 1600 koji_url='http://koji.fedoraproject.org/kojihub' # this was originally designed to check tags in pre-release (f15) and this may # not produce appropriate results for any released version of fedora or rawhide class check_tags: def __init__(self): time = datetime.datetime.now() self.starttime = time.strftime('%Y-%m-%d %H:%M') self.filename = "tag_report-%s-%s" % (rel, time.strftime('%Y-%m-%d-%H%M')) # to store the results in self.builds = {} self.ok_builds = [] self.stale_tag_builds = [] self.missing_tag_builds = [] # initialize koji and bodhi self.koji = koji.ClientSession(koji_url) # make sure we have a connection apiversion = self.koji.getAPIVersion() if apiversion != koji.API_VERSION: print "ERROR: apiversion %d does not match local version %d"\ % (apiversion, self.koji.API_VERSION) ops = {} self.bodhi = fedora.client.bodhi.BodhiClient(username=user, password=password, **ops) def get_koji_info(self): ks = koji.ClientSession.__init__(self.koji, koji_url) print "getting updates-pending from koji" self.koji_testing = self.get_koji_tag_nvrs('dist-f15-updates-pending') print "getting updates-testing-pending from koji" self.koji_testing_pending = self.get_koji_tag_nvrs('dist-f15-updates-testing-pending') def get_koji_tag_nvrs(self, tag): nvr_list = [] print "listing %s from koji" % tag res = self.koji.listTagged(tag) for r in res: nvr_list.append(r['nvr']) return nvr_list def get_koji_tags(self, nvr): tag_names = [] tags = self.koji.listTags(nvr) for tag in tags: tag_names.append(tag['name']) return tag_names def get_bodhi_updates(self, status): build_list = [] res = self.bodhi.query(status=status, release=rel, limit=bodhi_limit) for update in res['updates']: for build in update['builds']: build_list.append(build['nvr']) return build_list def get_bodhi_info(self): #self.bodhi_testing = self.get_bodhi_updates('testing') self.bodhi_stable = self.get_bodhi_updates('stable') #self.bodhi_obsolete = self.get_bodhi_updates('obsolete') def dump_bodhi_info(self): print "stable:" for build in self.bodhi_stable: print " %s" % build print "\ntesting:" for build in self.bodhi_testing: print " %s" % build print "\nobsolete:" for build in self.bodhi_obsolete: print " %s" % build def dump_koji_info(self): print "dist-f15-updates-testing:" for nvr in self.koji_testing: print " %s" % nvr print "dist-f15-updates-testing-pending:" for nvr in self.koji_testing_pending: print " %s" % nvr # actually do the comparison def compare_lists(self): print "Checking up to %d stable builds from bodhi" % bodhi_limit self.get_bodhi_info() total_updates = len(self.bodhi_stable) num_updates = 0 print "Got %d builds from bodhi" % total_updates for nvr in self.bodhi_stable: num_updates += 1 print "%4d/%4d - %s" % (num_updates, total_updates, nvr) self.builds[nvr] = {} self.builds[nvr]['stale'] = [] self.builds[nvr]['missing'] = [] is_ok = True tags = self.get_koji_tags(nvr) for tag in tags: if tag in stale_tags: self.builds[nvr]['stale'].append(tag) if not nvr in self.stale_tag_builds: self.stale_tag_builds.append(nvr) is_ok = False for tag in good_tags: if tag not in tags: self.builds[nvr]['missing'].append(tag) if not nvr in self.missing_tag_builds: self.missing_tag_builds.append(nvr) is_ok = False if is_ok: self.ok_builds.append(nvr) # output the collected data into a log def dump_data(self): print "\nWriting output to %s" % self.filename log = open(self.filename, 'w') try: log.write("Tag Report for %s generated at %s\n\n"% (rel, self.starttime)) log.write("Summary:\n") log.write(" %d builds evaluated\n" % len(self.bodhi_stable)) log.write(" * %d builds with stale tags\n" % len(self.stale_tag_builds)) log.write(" * %d builds with missing tags\n" % len(self.missing_tag_builds)) log.write("\n\n") if len(self.stale_tag_builds) > 0: log.write("----------------------------------------\n") log.write("| Stale Tags\n") log.write("----------------------------------------\n") log.write("\n%d builds with stale tags found!\n" % len(self.stale_tag_builds)) for build in self.stale_tag_builds: log.write("\n%s\n"% build) for tag in self.builds[build]['stale']: log.write(" * %s\n"% tag) log.write("\n") if len(self.missing_tag_builds) > 0: log.write("----------------------------------------\n") log.write("| Missing Tags\n") log.write("----------------------------------------\n") for build in self.missing_tag_builds: log.write("\n%s\n"% build) for tag in self.builds[build]['missing']: log.write(" * %s\n"% tag) log.write("\n") if len(self.ok_builds) > 0: log.write("----------------------------------------\n") log.write("| OK Builds\n") log.write("----------------------------------------\n\n") for build in self.ok_builds: log.write( "%s\n"% build) finally: log.close() if __name__ == "__main__": check = check_tags() check.compare_lists() check.dump_data()