pungi/pungi/phases/osbs.py
Lubomír Sedlář e7c8b2affd osbs: Validate config in tests
This makes sure the test configurations will be accepted in real usage.
It also enables us to remove some manual error checking that will be
performed by validator.

Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
2017-01-04 09:47:26 +01:00

134 lines
5.1 KiB
Python

# -*- coding: utf-8 -*-
import json
import os
from kobo.threads import ThreadPool, WorkerThread
from kobo import shortcuts
from .base import ConfigGuardedPhase, PhaseLoggerMixin
from .. import util
from ..wrappers import kojiwrapper
from ..paths import translate_path
class OSBSPhase(PhaseLoggerMixin, ConfigGuardedPhase):
name = 'osbs'
def __init__(self, compose):
super(OSBSPhase, self).__init__(compose)
self.pool = ThreadPool(logger=self.logger)
self.pool.metadata = {}
def run(self):
for variant in self.compose.get_variants():
for conf in util.get_variant_data(self.compose.conf, self.name, variant):
self.pool.add(OSBSThread(self.pool))
self.pool.queue_put((self.compose, variant, conf))
self.pool.start()
def dump_metadata(self):
"""Create a file with image metadata if the phase actually ran."""
if self._skipped:
return
with open(self.compose.paths.compose.metadata('osbs.json'), 'w') as f:
json.dump(self.pool.metadata, f, indent=4, sort_keys=True,
separators=(',', ': '))
class OSBSThread(WorkerThread):
def process(self, item, num):
compose, variant, config = item
self.num = num
with util.failable(compose, bool(config.pop('failable', None)), variant, '*', 'osbs',
logger=self.pool._logger):
self.worker(compose, variant, config)
def worker(self, compose, variant, config):
msg = 'OSBS phase for variant %s' % variant.uid
self.pool.log_info('[BEGIN] %s' % msg)
koji = kojiwrapper.KojiWrapper(compose.conf['koji_profile'])
koji.login()
# Start task
source = util.resolve_git_url(config.pop('url'))
target = config.pop('target')
priority = config.pop('priority', None)
repos = shortcuts.force_list(config.pop('repo', []))
compose_repos = [self._get_repo(compose, v)
for v in [variant.uid] + shortcuts.force_list(
config.pop('repo_from', []))]
config['yum_repourls'] = compose_repos + repos
task_id = koji.koji_proxy.buildContainer(source, target, config,
priority=priority)
# Wait for it to finish and capture the output into log file (even
# though there is not much there).
log_dir = os.path.join(compose.paths.log.topdir(), 'osbs')
util.makedirs(log_dir)
log_file = os.path.join(log_dir, '%s-%s-watch-task.log'
% (variant.uid, self.num))
if koji.watch_task(task_id, log_file) != 0:
raise RuntimeError('OSBS: task %s failed: see %s for details'
% (task_id, log_file))
# Only real builds get the metadata.
if not config.get('scratch', False):
self._add_metadata(koji.koji_proxy, variant, task_id)
self.pool.log_info('[DONE ] %s' % msg)
def _add_metadata(self, koji_proxy, variant, task_id):
# Create metadata
result = koji_proxy.getTaskResult(task_id)
build_id = int(result['koji_builds'][0])
buildinfo = koji_proxy.getBuild(build_id)
archives = koji_proxy.listArchives(build_id)
metadata = {
'name': buildinfo['name'],
'version': buildinfo['version'],
'release': buildinfo['release'],
'creation_time': buildinfo['creation_time'],
}
for archive in archives:
data = {
'filename': archive['filename'],
'size': archive['size'],
'checksum': archive['checksum'],
}
data.update(archive['extra'])
data.update(metadata)
arch = archive['extra']['image']['arch']
self.pool.log_debug('Created Docker base image %s-%s-%s.%s' % (
metadata['name'], metadata['version'], metadata['release'], arch))
self.pool.metadata.setdefault(
variant.uid, {}).setdefault(arch, []).append(data)
def _get_repo(self, compose, variant_uid):
"""
Write a .repo file pointing to current variant and return URL to the
file.
"""
try:
variant = compose.all_variants[variant_uid]
except KeyError:
raise RuntimeError(
'There is no variant %s to get repo from to pass to OSBS.'
% (variant_uid))
os_tree = compose.paths.compose.os_tree('$basearch', variant,
create_dir=False)
repo_file = os.path.join(compose.paths.work.tmp_dir(None, variant),
'compose-rpms-%s.repo' % self.num)
with open(repo_file, 'w') as f:
f.write('[%s]\n' % compose.compose_id)
f.write('name=Compose %s (RPMs)\n' % compose.compose_id)
f.write('baseurl=%s\n' % translate_path(compose, os_tree))
f.write('enabled=1\n')
f.write('gpgcheck=0\n')
return translate_path(compose, repo_file)