Add rabbit-repoid
This is a rather small tool that monitors all repositories below given namespaces and commits their repo ids to a git (has to run from the checkout). This git is then used as a trigger point for gocd pipelines
This commit is contained in:
parent
fa6e49559b
commit
eb8a2265df
137
rabbit-repoid.py
Executable file
137
rabbit-repoid.py
Executable file
@ -0,0 +1,137 @@
|
|||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import datetime
|
||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
|
||||||
|
import osc
|
||||||
|
from osc.core import http_GET, makeurl
|
||||||
|
|
||||||
|
from osclib.core import target_archs
|
||||||
|
from lxml import etree as ET
|
||||||
|
|
||||||
|
try:
|
||||||
|
from urllib.error import HTTPError
|
||||||
|
except ImportError:
|
||||||
|
# python 2.x
|
||||||
|
from urllib2 import HTTPError
|
||||||
|
|
||||||
|
from PubSubConsumer import PubSubConsumer
|
||||||
|
|
||||||
|
class Listener(PubSubConsumer):
|
||||||
|
def __init__(self, apiurl, amqp_prefix, namespaces):
|
||||||
|
super(Listener, self).__init__(amqp_prefix, logging.getLogger(__name__))
|
||||||
|
self.apiurl = apiurl
|
||||||
|
self.amqp_prefix = amqp_prefix
|
||||||
|
self.namespaces = namespaces
|
||||||
|
|
||||||
|
def routing_keys(self):
|
||||||
|
return [self.amqp_prefix + '.obs.repo.build_finished']
|
||||||
|
|
||||||
|
def check_arch(self, project, repository, architecture):
|
||||||
|
url = makeurl(self.apiurl, [
|
||||||
|
'build', project, repository, architecture], {'view': 'status'})
|
||||||
|
root = ET.parse(http_GET(url)).getroot()
|
||||||
|
if root.get('code') == 'finished':
|
||||||
|
buildid = root.find('buildid')
|
||||||
|
if buildid is not None:
|
||||||
|
return buildid.text
|
||||||
|
|
||||||
|
def check_all_archs(self, project, repository):
|
||||||
|
ids = {}
|
||||||
|
try:
|
||||||
|
archs = target_archs(self.apiurl, project, repository)
|
||||||
|
except HTTPError:
|
||||||
|
return None
|
||||||
|
for arch in archs:
|
||||||
|
repoid = self.check_arch(project, repository, arch)
|
||||||
|
if not repoid:
|
||||||
|
self.logger.info('{}/{}/{} not yet done'.format(project, repository, arch))
|
||||||
|
return None
|
||||||
|
ids[arch] = repoid
|
||||||
|
self.logger.info('All of {}/{} finished'.format(project, repository))
|
||||||
|
return ids
|
||||||
|
|
||||||
|
def is_part_of_namespaces(self, project):
|
||||||
|
for namespace in self.namespaces:
|
||||||
|
if project.startswith(namespace):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def start_consuming(self):
|
||||||
|
# now we are (re-)connected to the bus and need to fetch the
|
||||||
|
# initial state
|
||||||
|
for namespace in self.namespaces:
|
||||||
|
for state in glob.glob('{}*.yaml'.format(namespace)):
|
||||||
|
state = state.replace('.yaml', '')
|
||||||
|
# split
|
||||||
|
project, repository = state.split('_-_')
|
||||||
|
self.update_repo(project, repository)
|
||||||
|
self.push_git('Restart of Repo Monitor')
|
||||||
|
self.logger.info('Finished refreshing repoids')
|
||||||
|
super(Listener, self).start_consuming()
|
||||||
|
|
||||||
|
def push_git(self, message):
|
||||||
|
os.system('git add . ')
|
||||||
|
os.system('git commit -m "{}" > /dev/null'.format(message))
|
||||||
|
os.system('git push > /dev/null')
|
||||||
|
|
||||||
|
def update_repo(self, project, repository):
|
||||||
|
ids = self.check_all_archs(project, repository)
|
||||||
|
if not ids:
|
||||||
|
return
|
||||||
|
pathname = project + '_-_' + repository + '.yaml'
|
||||||
|
with open(pathname, 'w') as f:
|
||||||
|
for arch in sorted(ids.keys()):
|
||||||
|
f.write('{}: {}\n'.format(arch, ids[arch]))
|
||||||
|
|
||||||
|
def on_message(self, unused_channel, method, properties, body):
|
||||||
|
try:
|
||||||
|
body = json.loads(body)
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
|
if method.routing_key.endswith('.obs.repo.build_finished'):
|
||||||
|
if not self.is_part_of_namespaces(body['project']):
|
||||||
|
return
|
||||||
|
self.restart_timer()
|
||||||
|
self.logger.info('Repo finished event: {}/{}/{}'.format(body['project'], body['repo'], body['arch']))
|
||||||
|
self.update_repo(body['project'], body['repo'])
|
||||||
|
self.push_git('Repository finished: {}/{}'.format(body['project'], body['repo']))
|
||||||
|
else:
|
||||||
|
self.logger.warning(
|
||||||
|
'unknown rabbitmq message {}'.format(method.routing_key))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Monitor to commit repo status to git (for gocd trigger)')
|
||||||
|
parser.add_argument('--apiurl', '-A', type=str, help='API URL of OBS')
|
||||||
|
parser.add_argument('-d', '--debug', action='store_true', default=False,
|
||||||
|
help='enable debug information')
|
||||||
|
parser.add_argument('namespaces', nargs='*', help='namespaces to wait for')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
osc.conf.get_config(override_apiurl=args.apiurl)
|
||||||
|
osc.conf.config['debug'] = args.debug
|
||||||
|
|
||||||
|
apiurl = osc.conf.config['apiurl']
|
||||||
|
|
||||||
|
if apiurl.endswith('suse.de'):
|
||||||
|
amqp_prefix = 'suse'
|
||||||
|
else:
|
||||||
|
amqp_prefix = 'opensuse'
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
listener = Listener(apiurl, amqp_prefix, args.namespaces)
|
||||||
|
|
||||||
|
try:
|
||||||
|
listener.run(3600)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
listener.stop()
|
Loading…
x
Reference in New Issue
Block a user