Merge #595 Fix PEP8 issues

This commit is contained in:
Ralph Bean
2017-07-18 13:26:38 +00:00
43 changed files with 282 additions and 289 deletions

View File

@@ -1,17 +1,12 @@
import json
import requests
import os
import sys
import yaml
import pdc_client
filename = 'bootstrap-master-1.json'
print("Reading %s" % filename)
with open(filename, 'r') as f:
entry = json.loads(f.read())
print entry['modulemd']
print(entry['modulemd'])
modulemd = yaml.load(entry['modulemd'])
mbs = {}
mbs['commit'] = modulemd['data']['xmd']['mbs_commit']

View File

@@ -1,5 +1,4 @@
import json
import requests
import os
import sys

View File

@@ -5,7 +5,7 @@ from os import path
confdir = path.abspath(path.dirname(__file__))
# use parent dir as dbdir else fallback to current dir
dbdir = path.abspath(path.join(confdir, '..')) if confdir.endswith('conf') \
else confdir
else confdir
class BaseConfiguration(object):
@@ -67,7 +67,7 @@ class BaseConfiguration(object):
ALLOWED_GROUPS = set([
'packager',
#'modularity-wg',
# 'modularity-wg',
])
# Available backends are: console, file, journal.
@@ -172,6 +172,7 @@ class TestConfiguration(BaseConfiguration):
class ProdConfiguration(BaseConfiguration):
pass
class LocalBuildConfiguration(BaseConfiguration):
LOG_LEVEL = 'debug'
MESSAGING = 'in_memory'

View File

@@ -13,7 +13,7 @@ config = {
"endpoints": {
"fedora-infrastructure": [
# Just listen to staging for now, not to production (spam!)
#"tcp://hub.fedoraproject.org:9940",
# "tcp://hub.fedoraproject.org:9940",
"tcp://stg.fedoraproject.org:9940",
],
},

View File

@@ -59,6 +59,7 @@ conf = init_config(app)
db = SQLAlchemy(app)
@app.errorhandler(ValidationError)
def validationerror_error(e):
"""Flask error handler for ValidationError exceptions"""
@@ -104,6 +105,7 @@ init_logging(conf)
log = getLogger(__name__)
build_logs = ModuleBuildLogs(conf.build_logs_dir)
def get_url_for(*args, **kwargs):
"""
flask.url_for wrapper which creates the app_context on-the-fly.
@@ -116,8 +118,9 @@ def get_url_for(*args, **kwargs):
app.config['SERVER_NAME'] = 'localhost'
with app.app_context():
log.debug("WARNING: get_url_for() has been called without the Flask "
"app_context. That can lead to SQLAlchemy errors caused by "
"multiple session being used in the same time.")
"app_context. That can lead to SQLAlchemy errors caused by "
"multiple session being used in the same time.")
return url_for(*args, **kwargs)
from module_build_service import views

View File

@@ -37,18 +37,20 @@ def _json_loads(content):
client_secrets = None
def _load_secrets():
global client_secrets
if client_secrets:
return
if not "OIDC_CLIENT_SECRETS" in app.config:
if "OIDC_CLIENT_SECRETS" not in app.config:
raise Forbidden("OIDC_CLIENT_SECRETS must be set in server config.")
secrets = _json_loads(open(app.config['OIDC_CLIENT_SECRETS'],
'r').read())
'r').read())
client_secrets = list(secrets.values())[0]
def _get_token_info(token):
"""
Asks the token_introspection_uri for the validity of a token.
@@ -57,9 +59,9 @@ def _get_token_info(token):
return None
request = {'token': token,
'token_type_hint': 'Bearer',
'client_id': client_secrets['client_id'],
'client_secret': client_secrets['client_secret']}
'token_type_hint': 'Bearer',
'client_id': client_secrets['client_id'],
'client_secret': client_secrets['client_secret']}
headers = {'Content-type': 'application/x-www-form-urlencoded'}
resp = requests.post(client_secrets['token_introspection_uri'], data=request, headers=headers)
@@ -89,7 +91,7 @@ def get_user(request):
_load_secrets()
if not "authorization" in request.headers:
if "authorization" not in request.headers:
raise Unauthorized("No 'authorization' header found.")
header = request.headers['authorization'].strip()
@@ -105,10 +107,10 @@ def get_user(request):
log.exception(error)
raise Exception(error)
if not data or not "active" in data or not data["active"]:
if not data or "active" not in data or not data["active"]:
raise Unauthorized("OIDC token invalid or expired.")
if not "OIDC_REQUIRED_SCOPE" in app.config:
if "OIDC_REQUIRED_SCOPE" not in app.config:
raise Forbidden("OIDC_REQUIRED_SCOPE must be set in server config.")
presented_scopes = data['scope'].split(' ')

View File

@@ -35,7 +35,6 @@ from copr.client import CoprClient
from copr.exceptions import CoprRequestException
from module_build_service import log
from module_build_service.models import ModuleBuild
import module_build_service.scm
import module_build_service.utils
@@ -70,7 +69,6 @@ class CoprModuleBuilder(GenericBuilder):
self.chroot = "custom-1-x86_64"
self.__prep = False
@classmethod
def _get_client(cls, config):
return CoprClient.create_from_file_config(config.copr_config)

View File

@@ -57,7 +57,6 @@ class KojiContentGenerator(object):
self.mmd = module.modulemd
self.config = config
def __repr__(self):
return "<KojiContentGenerator module: %s>" % (self.module_name)
@@ -185,7 +184,7 @@ class KojiContentGenerator(object):
try:
rpms, builds = session.listTaggedRPMS(tag, latest=True)
except koji.GenericError as e:
except koji.GenericError:
log.exception("Failed to list rpms in tag %r", tag)
# If the tag doesn't exist.. then there are no rpms in that tag.
return []
@@ -244,7 +243,6 @@ class KojiContentGenerator(object):
}
return ret
def _get_output(self, output_path):
ret = []
rpms = self._koji_rpms_in_tag(self.module.koji_tag)
@@ -302,7 +300,6 @@ class KojiContentGenerator(object):
return ret
def _get_content_generator_metadata(self, output_path):
ret = {
u"metadata_version": 0,
@@ -327,11 +324,10 @@ class KojiContentGenerator(object):
log_path = os.path.join(prepdir, "build.log")
try:
shutil.copy(build_logs.path(self.module.id), log_path)
except IOError, e:
except IOError as e:
log.exception(e)
return prepdir
def koji_import(self):
"""This method imports given module into the configured koji instance as
a content generator based build
@@ -345,7 +341,7 @@ class KojiContentGenerator(object):
build_info = session.CGImport(metadata, file_dir)
log.debug("Content generator import done: %s",
json.dumps(build_info, sort_keys=True, indent=4))
except Exception, e:
except Exception as e:
log.exception("Content generator import failed: %s", e)
raise e
finally:

View File

@@ -40,7 +40,7 @@ import threading
import munch
from OpenSSL.SSL import SysCallError
from module_build_service import conf, log, db
from module_build_service import log
import module_build_service.scm
import module_build_service.utils
from module_build_service.builder.utils import execute_cmd
@@ -80,9 +80,9 @@ class KojiModuleBuilder(GenericBuilder):
raise ValueError("No koji_arches specified in the config.")
# These eventually get populated by calling _connect and __prep is set to True
self.module_tag = None # string
self.module_build_tag = None # string
self.module_target = None # A koji target dict
self.module_tag = None # string
self.module_build_tag = None # string
self.module_target = None # A koji target dict
self.build_priority = config.koji_build_priority
self.components = components
@@ -127,11 +127,10 @@ class KojiModuleBuilder(GenericBuilder):
log.info("%r buildroot is not yet ready.. wait." % self)
return ready
@staticmethod
def get_disttag_srpm(disttag, module_build):
#Taken from Karsten's create-distmacro-pkg.sh
# Taken from Karsten's create-distmacro-pkg.sh
# - however removed any provides to system-release/redhat-release
name = 'module-build-macros'
@@ -284,7 +283,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
# Create or update individual tags
self.module_tag = self._koji_create_tag(
self.tag_name, self.arches, perm="admin") # the main tag needs arches so pungi can dump it
self.tag_name, self.arches, perm="admin") # the main tag needs arches so pungi can dump it
self.module_build_tag = self._koji_create_tag(
self.tag_name + "-build", self.arches, perm="admin")
@@ -370,7 +369,8 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
log.info("Waiting for task_id=%s to finish" % task_id)
timeout = 60 * 60 # 60 minutes
timeout = 60 * 60 # 60 minutes
@module_build_service.utils.retry(timeout=timeout, wait_on=koji.GenericError)
def get_result():
log.debug("Waiting for task_id=%s to finish" % task_id)
@@ -467,9 +467,9 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
source, task_info['task_id'], self))
return task_info['task_id'], koji.BUILD_STATES['COMPLETE'], 'Build already exists.', task_info['nvr']
self._koji_whitelist_packages([artifact_name,])
self._koji_whitelist_packages([artifact_name])
if '://' not in source:
#treat source as an srpm and upload it
# treat source as an srpm and upload it
serverdir = _unique_path('cli-build')
callback = None
self.koji_session.uploadWrapper(source, serverdir, callback=callback)
@@ -480,8 +480,8 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
# The reason is that it is faster to build this RPM in
# already existing shared target, because Koji does not need to do
# repo-regen.
if (artifact_name == "module-build-macros"
and self.config.koji_build_macros_target):
if (artifact_name == "module-build-macros" and
self.config.koji_build_macros_target):
module_target = self.config.koji_build_macros_target
else:
module_target = self.module_target['name']
@@ -536,13 +536,14 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
priority = 0
if inheritance_data:
priority = inheritance_data[-1]['priority'] + 10
def record_exists(parent_id, data):
for item in data:
if parent_id == item['parent_id']:
return True
return False
for parent in parent_tags: # We expect that they're sorted
for parent in parent_tags: # We expect that they're sorted
parent = self._get_tag(parent)
if record_exists(parent['id'], inheritance_data):
continue
@@ -571,10 +572,10 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
raise ValueError("Expected dict {'group' : [str(package1), ...]")
dest_tag = self._get_tag(dest_tag)['name']
existing_groups = dict([
(p['name'], p['group_id'])
for p in self.koji_session.getTagGroups(dest_tag, inherit=False)
])
existing_groups = dict([(p['name'], p['group_id'])
for p
in self.koji_session.getTagGroups(dest_tag, inherit=False)
])
for group, packages in groups.items():
group_id = existing_groups.get(group, None)
@@ -589,7 +590,6 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
for pkg in packages:
self.koji_session.groupPackageListAdd(dest_tag, group, pkg)
@module_build_service.utils.validate_koji_tag('tag_name')
def _koji_create_tag(self, tag_name, arches=None, perm=None):
"""
@@ -613,8 +613,8 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
raise ValueError("Expected list or None on input got %s" % type(arches))
current_arches = []
if taginfo['arches']: # None if none
current_arches = taginfo['arches'].split() # string separated by empty spaces
if taginfo['arches']: # None if none
current_arches = taginfo['arches'].split() # string separated by empty spaces
if set(arches) != set(current_arches):
opts['arches'] = " ".join(arches)
@@ -629,7 +629,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
raise ValueError("Unknown permissions %s" % perm)
perm_id = perm_ids[perm]
if taginfo['perm'] not in (perm_id, perm): # check either id or the string
if taginfo['perm'] not in (perm_id, perm): # check either id or the string
opts['perm'] = perm_id
opts['extra'] = {
@@ -638,7 +638,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
# edit tag with opts
self.koji_session.editTag2(tag_name, **opts)
return self._get_tag(tag_name) # Return up2date taginfo
return self._get_tag(tag_name) # Return up2date taginfo
def _koji_whitelist_packages(self, packages, tags=None):
if not tags:
@@ -681,7 +681,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
if not target_info:
target_info = self.koji_session.createBuildTarget(name, build_tag['name'], dest_tag['name'])
else: # verify whether build and destination tag matches
else: # verify whether build and destination tag matches
if build_tag['name'] != target_info['build_tag_name']:
raise SystemError("Target references unexpected build_tag_name. Got '%s', expected '%s'. Please contact administrator." % (target_info['build_tag_name'], build_tag['name']))
if dest_tag['name'] != target_info['dest_tag_name']:
@@ -725,7 +725,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
# TODO: https://pagure.io/fm-orchestrator/issue/397
# Subj: Do not mix target/tag when looking for component builds
if (c.package == task_opts['mbs_artifact_name'] and
c.module_build.koji_tag == task_opts['mbs_module_target']):
c.module_build.koji_tag == task_opts['mbs_module_target']):
tasks.append(task)
return tasks

View File

@@ -28,10 +28,9 @@ import koji
import kobo.rpmlib
import modulemd
import pipes
import yaml
import threading
from module_build_service import conf, log, db
from module_build_service import conf, log
import module_build_service.scm
import module_build_service.utils
import module_build_service.scheduler
@@ -104,7 +103,7 @@ mdpolicy=group:primary
self.tag_name = tag_name
self.config = config
self.groups = []
self.arch = "x86_64" # TODO: We may need to change that in the future
self.arch = "x86_64" # TODO: We may need to change that in the future
self.yum_conf = MockModuleBuilder.MOCK_YUM_CONF_TEMPLATE
# Create main directory for this tag
@@ -183,7 +182,7 @@ mdpolicy=group:primary
pkglist_f.close()
mmd_path = os.path.join(path, "modules.yaml")
modulemd.dump_all(mmd_path, [ m1_mmd ])
modulemd.dump_all(mmd_path, [m1_mmd])
# Generate repo and inject modules.yaml there.
execute_cmd(['/usr/bin/createrepo_c', '--pkglist', pkglist, path])
@@ -477,8 +476,8 @@ class SCMBuilder(BaseBuilder):
# this code.
distgit_get_branch = \
"sh -c {}'; git -C {} checkout {}'".format(pipes.quote(distgit_get),
artifact_name,
branch)
artifact_name,
branch)
f.writelines([
"config_opts['scm'] = True\n",

View File

@@ -1,6 +1,7 @@
from module_build_service import conf
from base import GenericBuilder
from KojiModuleBuilder import KojiModuleBuilder
from MockModuleBuilder import MockModuleBuilder
__all__ = [
GenericBuilder
@@ -9,7 +10,6 @@ __all__ = [
GenericBuilder.register_backend_class(KojiModuleBuilder)
from MockModuleBuilder import MockModuleBuilder
GenericBuilder.register_backend_class(MockModuleBuilder)
if conf.system == "copr":

View File

@@ -60,6 +60,8 @@ Koji workflow
8) (optional) wait for selected builds to be available in buildroot
"""
class GenericBuilder(six.with_metaclass(ABCMeta)):
"""
External Api for builders

View File

@@ -8,7 +8,7 @@ import logging
import urlgrabber.grabber as grabber
import urlgrabber.progress as progress
import module_build_service
from module_build_service import log, scm, messaging
from module_build_service import log
logging.basicConfig(level=logging.DEBUG)
@@ -75,7 +75,7 @@ def create_local_repo_from_koji_tag(config, tag, repo_dir, archs=None):
# Get the list of all RPMs and builds in a tag.
try:
rpms, builds = session.listTaggedRPMS(tag, latest=True)
except koji.GenericError as e:
except koji.GenericError:
log.exception("Failed to list rpms in tag %r" % tag)
# Reformat builds so they are dict with build_id as a key.

View File

@@ -109,6 +109,7 @@ def init_config(app):
app.config.from_object(config_section_obj)
return conf
class Path:
"""
Config type for paths. Expands the users home directory.
@@ -189,14 +190,14 @@ class Config(object):
'desc': 'List of allowed koji tag prefixes.'},
'koji_target_delete_time': {
'type': int,
'default': 24*3600,
'default': 24 * 3600,
'desc': 'Time in seconds after which the Koji target of '
'built module is deleted'},
'built module is deleted'},
'koji_enable_content_generator': {
'type': bool,
'default': True,
'desc': 'Enable or disable imports to koji using content '
'generator api'},
'generator api'},
'allow_custom_scmurls': {
'type': bool,
'default': False,

View File

@@ -53,6 +53,7 @@ levels["info"] = logging.INFO
log_format = '%(asctime)s - %(threadName)s - %(name)s - %(levelname)s - %(message)s'
class ModuleBuildFileHandler(logging.FileHandler):
"""
FileHandler subclass which handles only messages generated during
@@ -138,14 +139,16 @@ def str_to_log_level(level):
Available levels are: debug, info, warning, error
"""
if not level in levels:
if level not in levels:
return logging.NOTSET
return levels[level]
def supported_log_backends():
return ("console", "journal", "file")
def init_logging(conf):
"""
Initializes logging according to configuration file.

View File

@@ -30,20 +30,11 @@ import ssl
from shutil import rmtree
import getpass
import fedmsg.config
import moksha.hub
import moksha.hub.hub
import moksha.hub.reactor
from module_build_service import app, conf, db
from module_build_service import models
from module_build_service.pdc import (
get_pdc_client_session, get_module,
get_module_tag, get_module_build_dependencies)
from module_build_service.utils import (
submit_module_build_from_scm,
)
from module_build_service.messaging import MBSModule
import module_build_service.messaging
import module_build_service.scheduler.consumer
@@ -154,7 +145,7 @@ def build_module_locally(url, branch, skiptests=False):
username = getpass.getuser()
submit_module_build_from_scm(username, url, branch, allow_local_url=True,
skiptests=skiptests)
skiptests=skiptests)
stop = module_build_service.scheduler.make_simple_stop_condition(db.session)

View File

@@ -265,6 +265,7 @@ class KojiBuildChange(BaseMessage):
self.module_build_id = module_build_id
self.state_reason = state_reason
class KojiTagChange(BaseMessage):
"""
A class that inherits from BaseMessage to provide a message
@@ -277,6 +278,7 @@ class KojiTagChange(BaseMessage):
self.tag = tag
self.artifact = artifact
class KojiRepoChange(BaseMessage):
""" A class that inherits from BaseMessage to provide a message
object for a repo's info (in fedmsg this replaces the msg dictionary)

View File

@@ -67,6 +67,7 @@ BUILD_STATES = {
INVERSE_BUILD_STATES = {v: k for k, v in BUILD_STATES.items()}
@contextlib.contextmanager
def _dummy_context_mgr():
"""
@@ -75,6 +76,7 @@ def _dummy_context_mgr():
"""
yield None
@contextlib.contextmanager
def make_session(conf):
"""
@@ -142,7 +144,7 @@ class ModuleBuild(MBSBase):
if not self.batch:
raise ValueError("No batch is in progress: %r" % self.batch)
if state != None:
if state is not None:
return [
component for component in self.component_builds
if component.batch == self.batch and component.state == state
@@ -162,7 +164,7 @@ class ModuleBuild(MBSBase):
if not self.batch:
raise ValueError("No batch is in progress: %r" % self.batch)
if state != None:
if state is not None:
return [
component for component in self.component_builds
if component.batch <= self.batch and component.state == state
@@ -339,7 +341,7 @@ class ModuleBuild(MBSBase):
'state_reason': self.state_reason,
"owner": self.owner,
"name": self.name,
"scmurl": self.scmurl,
"scmurl": self.scmurl,
"time_submitted": self._utc_datetime_to_iso(self.time_submitted),
"time_modified": self._utc_datetime_to_iso(self.time_modified),
"time_completed": self._utc_datetime_to_iso(self.time_completed),

View File

@@ -28,13 +28,11 @@
import modulemd
from pdc_client import PDCClient
import copy
import inspect
import pprint
import logging
log = logging.getLogger()
import six
log = logging.getLogger()
def get_pdc_client_session(config):
@@ -57,6 +55,7 @@ def get_pdc_client_session(config):
insecure=config.pdc_insecure,
)
def get_variant_dict(data):
"""
:param data: one of following
@@ -117,7 +116,6 @@ def get_variant_dict(data):
if 'variant_type' not in result.keys():
result['variant_type'] = 'module'
elif is_module_dict(data):
result = {'variant_id': data['name'], 'variant_version': data['version']}
@@ -144,13 +142,14 @@ def variant_dict_from_str(module_str):
release_start = module_str.rfind('-')
version_start = module_str.rfind('-', 0, release_start)
module_info['variant_release'] = module_str[release_start+1:]
module_info['variant_version'] = module_str[version_start+1:release_start]
module_info['variant_release'] = module_str[release_start + 1:]
module_info['variant_version'] = module_str[version_start + 1:release_start]
module_info['variant_id'] = module_str[:version_start]
module_info['variant_type'] = 'module'
return module_info
def get_module(session, module_info, strict=False):
"""
:param session : PDCClient instance
@@ -173,7 +172,7 @@ def get_module(session, module_info, strict=False):
if module_info.get('active'):
query['active'] = module_info['active']
retval = session['unreleasedvariants/'](page_size=-1, **query) # ordering=variant_release...
retval = session['unreleasedvariants/'](page_size=-1, **query) # ordering=variant_release...
# Error handling
if not retval:
@@ -197,6 +196,7 @@ def get_module(session, module_info, strict=False):
return module
def get_module_tag(session, module_info, strict=False):
"""
:param session : PDCClient instance
@@ -207,6 +207,7 @@ def get_module_tag(session, module_info, strict=False):
"""
return get_module(session, module_info, strict=strict)['koji_tag']
def get_module_modulemd(session, module_info, strict=False):
"""
:param session : PDCClient instance
@@ -223,17 +224,19 @@ def get_module_modulemd(session, module_info, strict=False):
if not yaml:
if strict:
raise ValueError("Failed to find modulemd entry in PDC for "
"%r" % module_info)
"%r" % module_info)
else:
return None
return _extract_modulemd(yaml, strict=strict)
def _extract_modulemd(yaml, strict=False):
mmd = modulemd.ModuleMetadata()
mmd.loads(yaml)
return mmd
def resolve_profiles(session, mmd, keys):
"""
:param session : PDCClient instance
@@ -266,6 +269,7 @@ def resolve_profiles(session, mmd, keys):
# Return the union of all rpms in all profiles of the given keys.
return results
def get_module_build_dependencies(session, module_info, strict=False):
"""
:param session : PDCClient instance
@@ -279,7 +283,6 @@ def get_module_build_dependencies(session, module_info, strict=False):
log.debug("get_module_build_dependencies(%r, strict=%r)" % (module_info, strict))
# XXX get definitive list of modules
deps = []
queried_module = get_module(session, module_info, strict=strict)
yaml = queried_module['modulemd']
queried_mmd = _extract_modulemd(yaml, strict=strict)
@@ -313,6 +316,7 @@ def get_module_build_dependencies(session, module_info, strict=False):
return module_tags
def get_module_commit_hash_and_version(session, module_info):
"""
Gets the commit hash and version of a module stored in PDC

View File

@@ -9,6 +9,7 @@ import module_build_service.scheduler.consumer
import logging
log = logging.getLogger(__name__)
def main(initial_messages, stop_condition):
""" Run the consumer until some condition is met.

View File

@@ -31,7 +31,6 @@ import itertools
import fedmsg.consumers
import moksha.hub
from module_build_service.errors import ValidationError
from module_build_service.utils import module_build_state_from_msg
import module_build_service.messaging
import module_build_service.scheduler.handlers.repos
@@ -47,9 +46,8 @@ class MBSConsumer(fedmsg.consumers.FedmsgConsumer):
"""
topic = ['{}.{}.'.format(pref.rstrip('.'), cat)
for pref, cat
in itertools.product(
conf.messaging_topic_prefix,
module_build_service.messaging._messaging_backends[conf.messaging]['services'])]
in itertools.product(conf.messaging_topic_prefix,
module_build_service.messaging._messaging_backends[conf.messaging]['services'])]
if not topic:
topic = '*'
log.debug('Setting topics: {}'.format(', '.join(topic)))

View File

@@ -68,10 +68,10 @@ def _finalize(config, session, msg, state):
parent = component_build.module_build
# If the macro build failed, then the module is doomed.
if (component_build.package == 'module-build-macros'
and state != koji.BUILD_STATES['COMPLETE']):
if (component_build.package == 'module-build-macros' and
state != koji.BUILD_STATES['COMPLETE']):
parent.transition(config, state=models.BUILD_STATES['failed'],
state_reason=state_reason)
state_reason=state_reason)
session.commit()
return
@@ -107,7 +107,7 @@ def _finalize(config, session, msg, state):
# change message here.
if failed_components_in_batch:
log.info("Batch done, but not tagging because of failed "
"component builds.")
"component builds.")
else:
log.info("Batch done. No component to tag")
further_work += [messaging.KojiRepoChange(
@@ -127,7 +127,7 @@ def _finalize(config, session, msg, state):
session.commit()
elif (any([c.state != koji.BUILD_STATES['BUILDING']
for c in unbuilt_components_in_batch])):
for c in unbuilt_components_in_batch])):
# We are not in the middle of the batch building and
# we have some unbuilt components in this batch. We might hit the
# concurrent builds threshold in previous call of continue_batch_build
@@ -144,8 +144,10 @@ def _finalize(config, session, msg, state):
def complete(config, session, msg):
return _finalize(config, session, msg, state=koji.BUILD_STATES['COMPLETE'])
def failed(config, session, msg):
return _finalize(config, session, msg, state=koji.BUILD_STATES['FAILED'])
def canceled(config, session, msg):
return _finalize(config, session, msg, state=koji.BUILD_STATES['CANCELED'])

View File

@@ -29,7 +29,7 @@ import module_build_service.pdc
import module_build_service.utils
import module_build_service.messaging
from module_build_service.utils import (
start_next_batch_build, attempt_to_reuse_all_components,
attempt_to_reuse_all_components,
get_rpm_release_from_mmd)
from module_build_service.builder.KojiContentGenerator import KojiContentGenerator
@@ -46,6 +46,7 @@ logging.basicConfig(level=logging.DEBUG)
def get_artifact_from_srpm(srpm_path):
return os.path.basename(srpm_path).replace(".src.rpm", "")
def failed(config, session, msg):
"""
Called whenever a module enters the 'failed' state.
@@ -66,8 +67,8 @@ def failed(config, session, msg):
unbuilt_components = [
c for c in build.component_builds
if (c.state != koji.BUILD_STATES['COMPLETE']
and c.state != koji.BUILD_STATES["FAILED"])
if (c.state != koji.BUILD_STATES['COMPLETE'] and
c.state != koji.BUILD_STATES["FAILED"])
]
if build.koji_tag:
@@ -120,6 +121,7 @@ def done(config, session, msg):
build_logs.stop(build.id)
def wait(config, session, msg):
""" Called whenever a module enters the 'wait' state.
@@ -161,9 +163,9 @@ def wait(config, session, msg):
if conf.system != "koji":
# In case of mock, we do not try to get anything from pdc,
# just generate our own koji_tag to identify the module in messages.
tag = '-'.join(['module', module_info['name'],
str(module_info['stream']), str(module_info['version'])])
tag = '-'.join(['module',
module_info['name'],
str(module_info['stream']), str(module_info['version'])])
for name, stream in build.mmd().buildrequires.items():
@@ -218,9 +220,6 @@ def wait(config, session, msg):
session.commit()
raise
groups = module_build_service.builder.GenericBuilder.default_buildroot_groups(
session, build)
log.debug("Found tag=%s for module %r" % (tag, build))
# Hang on to this information for later. We need to know which build is
# associated with which koji tag, so that when their repos are regenerated
@@ -279,7 +278,7 @@ def wait(config, session, msg):
if state == koji.BUILD_STATES['COMPLETE']:
if config.system == "koji":
log.info("module-build-macros is already built. "
"Regenerating the repo.")
"Regenerating the repo.")
task_id = builder.koji_session.newRepo(
builder.module_build_tag['name'])
build.new_repo_task_id = task_id

View File

@@ -28,7 +28,6 @@ import module_build_service.pdc
import logging
import koji
from module_build_service import models, log
from module_build_service.utils import start_next_batch_build
logging.basicConfig(level=logging.DEBUG)

View File

@@ -51,7 +51,7 @@ class MBSProducer(PollingProducer):
self.process_paused_module_builds(conf, session)
self.trigger_new_repo_when_stalled(conf, session)
self.delete_old_koji_targets(conf, session)
except Exception as e:
except Exception:
msg = 'Error in poller execution:'
log.exception(msg)
@@ -155,7 +155,7 @@ class MBSProducer(PollingProducer):
# First batch is number '1'.
for i in range(1, module_build.batch + 1):
n = len([c for c in module_build.component_builds
if c.batch == i ])
if c.batch == i])
log.info(' * {0} components in batch {1}'
.format(n, i))
@@ -189,14 +189,13 @@ class MBSProducer(PollingProducer):
# Check to see if module builds that are in build state but don't have
# any component builds being built can be worked on
for module_build in session.query(models.ModuleBuild).filter_by(
state=models.BUILD_STATES['build']).all():
for module_build in session.query(models.ModuleBuild).filter_by(state=models.BUILD_STATES['build']).all():
# If there are no components in the build state on the module build,
# then no possible event will start off new component builds.
# But do not try to start new builds when we are waiting for the
# repo-regen.
if (not module_build.current_batch(koji.BUILD_STATES['BUILDING'])
and not module_build.new_repo_task_id):
if (not module_build.current_batch(koji.BUILD_STATES['BUILDING']) and
not module_build.new_repo_task_id):
# Initialize the builder...
builder = GenericBuilder.create_from_module(
session, module_build, config)
@@ -224,8 +223,7 @@ class MBSProducer(PollingProducer):
koji_session = module_build_service.builder.KojiModuleBuilder\
.get_session(config, None)
for module_build in session.query(models.ModuleBuild).filter_by(
state=models.BUILD_STATES['build']).all():
for module_build in session.query(models.ModuleBuild).filter_by(state=models.BUILD_STATES['build']).all():
if not module_build.new_repo_task_id:
continue

View File

@@ -27,8 +27,6 @@
"""SCM handler functions."""
from six.moves import http_client
import os
import subprocess as sp
import re
@@ -169,7 +167,7 @@ class SCM(object):
"The original message was: %s" % e.message)
raise
timestamp = SCM._run(["git", "show" , "-s", "--format=%ct"], chdir=sourcedir)[1]
timestamp = SCM._run(["git", "show", "-s", "--format=%ct"], chdir=sourcedir)[1]
dt = datetime.datetime.utcfromtimestamp(int(timestamp))
self.version = dt.strftime("%Y%m%d%H%M%S")
else:

View File

@@ -29,11 +29,8 @@ import time
import shutil
import tempfile
import os
import logging
import copy
import kobo.rpmlib
import inspect
from six import iteritems
import hashlib
import modulemd
@@ -53,6 +50,7 @@ from module_build_service.pdc import get_module_commit_hash_and_version
import concurrent.futures
def retry(timeout=conf.net_timeout, interval=conf.net_retry_interval, wait_on=Exception):
""" A decorator that allows to retry a section of code...
...until success or timeout.
@@ -104,6 +102,7 @@ def at_concurrent_component_threshold(config, session):
return False
def start_build_component(builder, c):
"""
Submits single component build to builder. Called in thread
@@ -122,9 +121,10 @@ def start_build_component(builder, c):
if not c.task_id and c.state == koji.BUILD_STATES['BUILDING']:
c.state = koji.BUILD_STATES['FAILED']
c.state_reason = ("Failed to build artifact %s: "
"Builder did not return task ID" % (c.package))
"Builder did not return task ID" % (c.package))
return
def continue_batch_build(config, module, session, builder, components=None):
"""
Continues building current batch. Submits next components in the batch
@@ -140,10 +140,10 @@ def continue_batch_build(config, module, session, builder, components=None):
# successfully built yet or isn't currently being built.
unbuilt_components = components or [
c for c in module.component_builds
if (c.state != koji.BUILD_STATES['COMPLETE']
and c.state != koji.BUILD_STATES['BUILDING']
and c.state != koji.BUILD_STATES['FAILED']
and c.batch == module.batch)
if (c.state != koji.BUILD_STATES['COMPLETE'] and
c.state != koji.BUILD_STATES['BUILDING'] and
c.state != koji.BUILD_STATES['FAILED'] and
c.batch == module.batch)
]
if not unbuilt_components:
@@ -162,8 +162,8 @@ def continue_batch_build(config, module, session, builder, components=None):
session, module, c.package)
# If a component build can't be reused, we need to check
# the concurrent threshold.
if (not previous_component_build
and at_concurrent_component_threshold(config, session)):
if (not previous_component_build and
at_concurrent_component_threshold(config, session)):
log.info('Concurrent build threshold met')
break
@@ -195,8 +195,8 @@ def continue_batch_build(config, module, session, builder, components=None):
# We therefore have to generate fake KojiRepoChange message, because the
# repo has been also done in the past and build system will not send us
# any message now.
if (all(c.state in [koji.BUILD_STATES['COMPLETE'], koji.BUILD_STATES['FAILED']]
or c.reused_component_id
if (all(c.state in [koji.BUILD_STATES['COMPLETE'],
koji.BUILD_STATES['FAILED']] or c.reused_component_id
for c in unbuilt_components) and builder.module_build_tag):
further_work += [module_build_service.messaging.KojiRepoChange(
'start_build_batch: fake msg', builder.module_build_tag['name'])]
@@ -204,6 +204,7 @@ def continue_batch_build(config, module, session, builder, components=None):
session.commit()
return further_work
def start_next_batch_build(config, module, session, builder, components=None):
"""
Tries to start the build of next batch. In case there are still unbuilt
@@ -294,10 +295,10 @@ def start_next_batch_build(config, module, session, builder, components=None):
# successfully built yet or isn't currently being built.
unbuilt_components = components or [
c for c in module.component_builds
if (c.state != koji.BUILD_STATES['COMPLETE']
and c.state != koji.BUILD_STATES['BUILDING']
and c.state != koji.BUILD_STATES['FAILED']
and c.batch == module.batch)
if (c.state != koji.BUILD_STATES['COMPLETE'] and
c.state != koji.BUILD_STATES['BUILDING'] and
c.state != koji.BUILD_STATES['FAILED'] and
c.batch == module.batch)
]
# If there are no components to build, skip the batch and start building
@@ -308,11 +309,12 @@ def start_next_batch_build(config, module, session, builder, components=None):
return start_next_batch_build(config, module, session, builder)
log.info("Starting build of next batch %d, %s" % (module.batch,
unbuilt_components))
unbuilt_components))
return continue_batch_build(
config, module, session, builder, unbuilt_components)
def pagination_metadata(p_query, request_args):
"""
Returns a dictionary containing metadata about the paginated query.
@@ -358,6 +360,7 @@ def pagination_metadata(p_query, request_args):
return pagination_data
def filter_component_builds(flask_request):
"""
Returns a flask_sqlalchemy.Pagination object based on the request parameters
@@ -398,12 +401,13 @@ def filter_component_builds(flask_request):
query = query.order_by(column)
else:
raise ValidationError('An invalid order_by or order_desc_by key '
'was supplied')
'was supplied')
page = flask_request.args.get('page', 1, type=int)
per_page = flask_request.args.get('per_page', 10, type=int)
return query.paginate(page, per_page, False)
def filter_module_builds(flask_request):
"""
Returns a flask_sqlalchemy.Pagination object based on the request parameters
@@ -468,7 +472,7 @@ def filter_module_builds(flask_request):
query = query.order_by(column)
else:
raise ValidationError('An invalid order_by or order_desc_by key '
'was supplied')
'was supplied')
page = flask_request.args.get('page', 1, type=int)
per_page = flask_request.args.get('per_page', 10, type=int)
@@ -567,6 +571,7 @@ def _scm_get_latest(pkg):
'error': None
}
def format_mmd(mmd, scmurl):
"""
Prepares the modulemd for the MBS. This does things such as replacing the
@@ -667,6 +672,7 @@ def format_mmd(mmd, scmurl):
if err_msg:
raise UnprocessableEntity(err_msg)
def merge_included_mmd(mmd, included_mmd):
"""
Merges two modulemds. This merges only metadata which are needed in
@@ -678,6 +684,7 @@ def merge_included_mmd(mmd, included_mmd):
else:
mmd.xmd['mbs']['rpms'].update(included_mmd.xmd['mbs']['rpms'])
def record_component_builds(mmd, module, initial_batch=1,
previous_buildorder=None, main_mmd=None):
import koji # Placed here to avoid py2/py3 conflicts...
@@ -788,6 +795,7 @@ def submit_module_build_from_yaml(username, handle, optional_params=None):
_url_check_re = re.compile(r"^[^:/]+:.*$")
def submit_module_build_from_scm(username, url, branch, allow_local_url=False,
skiptests=False, optional_params=None):
# Translate local paths into file:// URL
@@ -805,7 +813,6 @@ def submit_module_build_from_scm(username, url, branch, allow_local_url=False,
def submit_module_build(username, url, mmd, scm, yaml, optional_params=None):
# Import it here, because SCM uses utils methods
# and fails to import them because of dep-chain.
import module_build_service.scm
module = models.ModuleBuild.query.filter_by(
name=mmd.name, stream=mmd.stream, version=str(mmd.version)).first()
@@ -816,8 +823,8 @@ def submit_module_build(username, url, mmd, scm, yaml, optional_params=None):
if module.state not in (models.BUILD_STATES['failed'],
models.BUILD_STATES['init']):
err_msg = ('Module (state=%s) already exists. '
'Only new build or resubmission of build in "init" or '
'"failed" state is allowed.' % module.state)
'Only new build or resubmission of build in "init" or '
'"failed" state is allowed.' % module.state)
log.error(err_msg)
raise Conflict(err_msg)
log.debug('Resuming existing module build %r' % module)
@@ -870,9 +877,9 @@ def scm_url_schemes(terse=False):
"""
scm_types = {
"git": ("git://", "git+http://", "git+https://",
"git+rsync://", "http://", "https://", "file://")
}
"git": ("git://", "git+http://", "git+https://",
"git+rsync://", "http://", "https://", "file://")
}
if not terse:
return scm_types
@@ -882,12 +889,14 @@ def scm_url_schemes(terse=False):
scheme_list.extend([scheme[:-3] for scheme in scm_schemes])
return list(set(scheme_list))
def get_scm_url_re():
schemes_re = '|'.join(map(re.escape, scm_url_schemes(terse=True)))
return re.compile(
r"(?P<giturl>(?:(?P<scheme>(" + schemes_re + r"))://(?P<host>[^/]+))?"
r"(?P<repopath>/[^\?]+))\?(?P<modpath>[^#]*)#(?P<revision>.+)")
def module_build_state_from_msg(msg):
state = int(msg.module_build_state)
# TODO better handling
@@ -896,6 +905,7 @@ def module_build_state_from_msg(msg):
% (state, type(state), list(models.BUILD_STATES.values())))
return state
def reuse_component(component, previous_component_build,
change_state_now=False):
"""
@@ -943,6 +953,7 @@ def reuse_component(component, previous_component_build,
)
]
def attempt_to_reuse_all_components(builder, session, module):
"""
Tries to reuse all the components in a build. The components are also
@@ -986,6 +997,7 @@ def attempt_to_reuse_all_components(builder, session, module):
return True
def get_reusable_component(session, module, component_name):
"""
Returns the component (RPM) build of a module that can be reused
@@ -1221,6 +1233,7 @@ def validate_koji_tag(tag_arg_names, pre='', post='-', dict_key='name'):
return validation_decorator
def get_rpm_release_from_mmd(mmd):
"""
Returns the dist tag based on the modulemd metadata and MBS configuration.

View File

@@ -36,7 +36,7 @@ from module_build_service import models, db
from module_build_service.utils import (
pagination_metadata, filter_module_builds, filter_component_builds,
submit_module_build_from_scm, submit_module_build_from_yaml,
scm_url_schemes, get_scm_url_re)
get_scm_url_re)
from module_build_service.errors import (
ValidationError, Forbidden, NotFound)
@@ -69,6 +69,7 @@ api_v1 = {
},
}
class ComponentBuildAPI(MethodView):
def get(self, id):
@@ -206,8 +207,8 @@ class BaseHandler(object):
return {k: v for k, v in self.data.items() if k not in ["owner", "scmurl", "branch"]}
def validate_optional_params(self):
forbidden_params = [k for k in self.data if k not in models.ModuleBuild.__table__.columns
and k not in ["branch"]]
forbidden_params = [k for k in self.data if k not in models.ModuleBuild.__table__.columns and
k not in ["branch"]]
if forbidden_params:
raise ValidationError('The request contains unspecified parameters: {}'.format(", ".join(forbidden_params)))
@@ -289,11 +290,11 @@ def register_api_v1():
app.add_url_rule(val['url'],
endpoint=key,
view_func=module_view,
**val['options'])
**val['options'])
else:
app.add_url_rule(val['url'],
endpoint=key,
view_func=component_view,
**val['options'])
register_api_v1()

View File

@@ -21,7 +21,6 @@
# Written by Matt Prahl <mprahl@redhat.com
import os
import copy
import module_build_service
from datetime import datetime, timedelta
@@ -29,13 +28,13 @@ from module_build_service import db
from module_build_service.config import init_config
from module_build_service.models import ModuleBuild, ComponentBuild, make_session
import modulemd
from module_build_service.utils import get_scm_url_re
import module_build_service.pdc
base_dir = os.path.dirname(__file__)
app = module_build_service.app
conf = init_config(app)
def init_data():
db.session.remove()
db.drop_all()
@@ -399,6 +398,7 @@ def test_reuse_component_init_data():
session.add(component_four_build_two)
session.commit()
def test_reuse_shared_userspace_init_data():
db.session.remove()
db.drop_all()
@@ -419,7 +419,7 @@ def test_reuse_shared_userspace_init_data():
build_one = module_build_service.models.ModuleBuild()
build_one.name = mmd.name
build_one.stream = mmd.stream
build_one.stream = mmd.stream
build_one.version = mmd.version
build_one.state = 5
build_one.modulemd = yaml
@@ -466,7 +466,7 @@ def test_reuse_shared_userspace_init_data():
build_one = module_build_service.models.ModuleBuild()
build_one.name = mmd.name
build_one.stream = mmd.stream
build_one.stream = mmd.stream
build_one.version = mmd.version
build_one.state = 3
build_one.modulemd = yaml

View File

@@ -20,8 +20,7 @@
#
# Written by Ralph Bean <rbean@redhat.com>
from nose.tools import raises, eq_
from nose.tools import eq_
import unittest
import mock
@@ -42,10 +41,10 @@ class TestAuthModule(unittest.TestCase):
request.cookies.return_value = {}
with self.assertRaises(module_build_service.errors.Unauthorized) as cm:
result = module_build_service.auth.get_user(request)
module_build_service.auth.get_user(request)
self.assertEquals(str(cm.exception),
"No 'authorization' header found.")
"No 'authorization' header found.")
@patch('module_build_service.auth._get_token_info')
@patch('module_build_service.auth._get_user_info')
@@ -57,10 +56,10 @@ class TestAuthModule(unittest.TestCase):
# https://www.youtube.com/watch?v=G-LtddOgUCE
name = "Joey Jo Jo Junior Shabadoo"
mocked_get_token_info = {"active": False, "username": name,
"scope": "openid https://id.fedoraproject.org/scope/groups mbs-scope"}
"scope": "openid https://id.fedoraproject.org/scope/groups mbs-scope"}
get_token_info.return_value = mocked_get_token_info
get_user_info.return_value = {"groups":["group"]}
get_user_info.return_value = {"groups": ["group"]}
headers = {"authorization": "Bearer foobar"}
request = mock.MagicMock()
@@ -70,10 +69,10 @@ class TestAuthModule(unittest.TestCase):
request.headers.__contains__.side_effect = headers.__contains__
with self.assertRaises(module_build_service.errors.Unauthorized) as cm:
result = module_build_service.auth.get_user(request)
module_build_service.auth.get_user(request)
self.assertEquals(str(cm.exception),
"OIDC token invalid or expired.")
"OIDC token invalid or expired.")
@patch('module_build_service.auth._get_token_info')
@patch('module_build_service.auth._get_user_info')
@@ -85,10 +84,10 @@ class TestAuthModule(unittest.TestCase):
# https://www.youtube.com/watch?v=G-LtddOgUCE
name = "Joey Jo Jo Junior Shabadoo"
mocked_get_token_info = {"active": True, "username": name,
"scope": "openid https://id.fedoraproject.org/scope/groups mbs-scope"}
"scope": "openid https://id.fedoraproject.org/scope/groups mbs-scope"}
get_token_info.return_value = mocked_get_token_info
get_user_info.return_value = {"groups":["group"]}
get_user_info.return_value = {"groups": ["group"]}
headers = {"authorization": "Bearer foobar"}
request = mock.MagicMock()
@@ -115,7 +114,7 @@ class TestAuthModule(unittest.TestCase):
module_build_service.auth.get_user(request)
self.assertEquals(str(cm.exception),
"OIDC_CLIENT_SECRETS must be set in server config.")
"OIDC_CLIENT_SECRETS must be set in server config.")
@patch('module_build_service.auth._get_token_info')
@patch('module_build_service.auth._get_user_info')
@@ -126,11 +125,12 @@ class TestAuthModule(unittest.TestCase):
'OIDC_REQUIRED_SCOPE': 'mbs-scope'}):
# https://www.youtube.com/watch?v=G-LtddOgUCE
name = "Joey Jo Jo Junior Shabadoo"
mocked_get_token_info = {"active": True, "username": name,
"scope": "openid https://id.fedoraproject.org/scope/groups"}
mocked_get_token_info = {"active": True,
"username": name,
"scope": "openid https://id.fedoraproject.org/scope/groups"}
get_token_info.return_value = mocked_get_token_info
get_user_info.return_value = {"groups":["group"]}
get_user_info.return_value = {"groups": ["group"]}
headers = {"authorization": "Bearer foobar"}
request = mock.MagicMock()
@@ -140,11 +140,11 @@ class TestAuthModule(unittest.TestCase):
request.headers.__contains__.side_effect = headers.__contains__
with self.assertRaises(module_build_service.errors.Unauthorized) as cm:
result = module_build_service.auth.get_user(request)
module_build_service.auth.get_user(request)
self.assertEquals(str(cm.exception),
"Required OIDC scope 'mbs-scope' not present: "
"['openid', 'https://id.fedoraproject.org/scope/groups']")
"Required OIDC scope 'mbs-scope' not present: "
"['openid', 'https://id.fedoraproject.org/scope/groups']")
@patch('module_build_service.auth._get_token_info')
@patch('module_build_service.auth._get_user_info')
@@ -154,11 +154,12 @@ class TestAuthModule(unittest.TestCase):
with patch.dict('module_build_service.app.config', {'OIDC_CLIENT_SECRETS': client_secrets}):
# https://www.youtube.com/watch?v=G-LtddOgUCE
name = "Joey Jo Jo Junior Shabadoo"
mocked_get_token_info = {"active": True, "username": name,
"scope": "openid https://id.fedoraproject.org/scope/groups"}
mocked_get_token_info = {"active": True,
"username": name,
"scope": "openid https://id.fedoraproject.org/scope/groups"}
get_token_info.return_value = mocked_get_token_info
get_user_info.return_value = {"groups":["group"]}
get_user_info.return_value = {"groups": ["group"]}
headers = {"authorization": "Bearer foobar"}
request = mock.MagicMock()
@@ -168,7 +169,7 @@ class TestAuthModule(unittest.TestCase):
request.headers.__contains__.side_effect = headers.__contains__
with self.assertRaises(module_build_service.errors.Forbidden) as cm:
result = module_build_service.auth.get_user(request)
module_build_service.auth.get_user(request)
self.assertEquals(str(cm.exception),
"OIDC_REQUIRED_SCOPE must be set in server config.")
"OIDC_REQUIRED_SCOPE must be set in server config.")

View File

@@ -24,7 +24,7 @@ import unittest
import koji
import vcr
import os
from os import path, mkdir, remove
from os import path, mkdir
from os.path import dirname
from shutil import copyfile
@@ -38,7 +38,6 @@ from module_build_service import db, models, conf, build_logs
from mock import patch, PropertyMock
from tests import app, init_data, test_reuse_component_init_data
import os
import json
import itertools
@@ -51,6 +50,7 @@ cassette_dir = base_dir + '/vcr-request-data/'
user = ('Homer J. Simpson', set(['packager']))
class MockedSCM(object):
def __init__(self, mocked_scm, name, mmd_filename, commit=None):
self.mocked_scm = mocked_scm
@@ -70,13 +70,14 @@ class MockedSCM(object):
mkdir(scm_dir)
base_dir = path.abspath(path.dirname(__file__))
copyfile(path.join(base_dir, '..', 'staged_data', self.mmd_filename),
path.join(scm_dir, self.mmd_filename))
path.join(scm_dir, self.mmd_filename))
return scm_dir
def get_latest(self, branch='master'):
return branch
class TestModuleBuilder(GenericBuilder):
"""
Test module builder which succeeds for every build.
@@ -173,7 +174,7 @@ class TestModuleBuilder(GenericBuilder):
module_build_service.scheduler.consumer.work_queue_put(msg)
def build(self, artifact_name, source):
print "Starting building artifact %s: %s" % (artifact_name, source)
print("Starting building artifact %s: %s" % (artifact_name, source))
TestModuleBuilder._build_id += 1
@@ -207,18 +208,18 @@ class TestModuleBuilder(GenericBuilder):
@patch("module_build_service.config.Config.system",
new_callable=PropertyMock, return_value="test")
new_callable=PropertyMock, return_value="test")
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={
'srpm-build':
set(['shadow-utils', 'fedora-release', 'redhat-rpm-config',
'rpm-build', 'fedpkg-minimal', 'gnupg2', 'bash']),
'build':
set(['unzip', 'fedora-release', 'tar', 'cpio', 'gawk',
'gcc', 'xz', 'sed', 'findutils', 'util-linux', 'bash',
'info', 'bzip2', 'grep', 'redhat-rpm-config',
'diffutils', 'make', 'patch', 'shadow-utils',
'coreutils', 'which', 'rpm-build', 'gzip', 'gcc-c++'])})
'srpm-build':
set(['shadow-utils', 'fedora-release', 'redhat-rpm-config',
'rpm-build', 'fedpkg-minimal', 'gnupg2', 'bash']),
'build':
set(['unzip', 'fedora-release', 'tar', 'cpio', 'gawk',
'gcc', 'xz', 'sed', 'findutils', 'util-linux', 'bash',
'info', 'bzip2', 'grep', 'redhat-rpm-config',
'diffutils', 'make', 'patch', 'shadow-utils',
'coreutils', 'which', 'rpm-build', 'gzip', 'gcc-c++'])})
class TestBuild(unittest.TestCase):
# Global variable used for tests if needed
@@ -300,7 +301,7 @@ class TestBuild(unittest.TestCase):
# or "ready" state.
for build in models.ComponentBuild.query.filter_by(module_id=module_build_id).all():
self.assertEqual(build.state, koji.BUILD_STATES['COMPLETE'])
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]] )
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]])
# All components has to be tagged, so tag_groups and buildroot_groups are empty...
self.assertEqual(tag_groups, [])
@@ -323,13 +324,13 @@ class TestBuild(unittest.TestCase):
return json.loads(rv.data)
with patch("module_build_service.config.Config.yaml_submit_allowed",
new_callable=PropertyMock, return_value=True):
new_callable=PropertyMock, return_value=True):
conf.set_item("yaml_submit_allowed", True)
data = submit()
self.assertEqual(data['id'], 1)
with patch("module_build_service.config.Config.yaml_submit_allowed",
new_callable=PropertyMock, return_value=False):
new_callable=PropertyMock, return_value=False):
data = submit()
self.assertEqual(data['status'], 403)
self.assertEqual(data['message'], 'YAML submission is not enabled')
@@ -373,11 +374,11 @@ class TestBuild(unittest.TestCase):
# method. We just cancel the build here using the web API to simulate
# user cancelling the build in the middle of building.
def on_build_cb(cls, artifact_name, source):
self.client.patch(
'/module-build-service/1/module-builds/' + str(module_build_id),
data=json.dumps({'state': 'failed'}))
self.client.patch('/module-build-service/1/module-builds/' + str(module_build_id),
data=json.dumps({'state': 'failed'}))
cancelled_tasks = []
def on_cancel_cb(cls, task_id):
cancelled_tasks.append(task_id)
@@ -433,7 +434,7 @@ class TestBuild(unittest.TestCase):
# or "ready" state.
for build in models.ComponentBuild.query.filter_by(module_id=module_build_id).all():
self.assertEqual(build.state, koji.BUILD_STATES['COMPLETE'])
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]] )
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]])
@timed(30)
@patch('module_build_service.auth.get_user', return_value=user)
@@ -465,7 +466,7 @@ class TestBuild(unittest.TestCase):
main_stop = module_build_service.scheduler.make_simple_stop_condition(db.session)
over_threshold = conf.num_concurrent_builds < \
db.session.query(models.ComponentBuild).filter_by(
state=koji.BUILD_STATES['BUILDING']).count()
state=koji.BUILD_STATES['BUILDING']).count()
return main_stop(message) or over_threshold
msgs = []
@@ -477,7 +478,7 @@ class TestBuild(unittest.TestCase):
self.assertEqual(build.state, koji.BUILD_STATES['COMPLETE'])
# When this fails, it can mean that num_concurrent_builds
# threshold has been met.
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]] )
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]])
@timed(30)
@patch('module_build_service.auth.get_user', return_value=user)
@@ -600,7 +601,7 @@ class TestBuild(unittest.TestCase):
@patch("module_build_service.config.Config.num_concurrent_builds",
new_callable=PropertyMock, return_value=1)
def test_all_builds_in_batch_fail(self, conf_num_concurrent_builds, mocked_scm,
mocked_get_user, conf_system, dbg):
mocked_get_user, conf_system, dbg):
"""
Tests that if the build in batch fails, other components in a batch
are still build, but next batch is not started.
@@ -661,8 +662,8 @@ class TestBuild(unittest.TestCase):
tag_groups = []
tag_groups.append(set(
['perl-Tangerine-0.23-1.module_testmodule_master_20170109091357',
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
def on_tag_artifacts_cb(cls, artifacts):
self.assertEqual(tag_groups.pop(0), set(artifacts))
@@ -671,8 +672,9 @@ class TestBuild(unittest.TestCase):
buildtag_groups = []
buildtag_groups.append(set(
['perl-Tangerine-0.23-1.module_testmodule_master_20170109091357',
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
def on_buildroot_add_artifacts_cb(cls, artifacts, install):
self.assertEqual(buildtag_groups.pop(0), set(artifacts))
TestModuleBuilder.on_buildroot_add_artifacts_cb = on_buildroot_add_artifacts_cb
@@ -697,7 +699,7 @@ class TestBuild(unittest.TestCase):
@patch('module_build_service.auth.get_user', return_value=user)
@patch('module_build_service.scm.SCM')
def test_submit_build_reuse_all_without_build_macros(self, mocked_scm, mocked_get_user,
conf_system, dbg):
conf_system, dbg):
"""
Tests that we can reuse components even when the reused module does
not have module-build-macros component.
@@ -718,8 +720,8 @@ class TestBuild(unittest.TestCase):
tag_groups = []
tag_groups.append(set(
['perl-Tangerine-0.23-1.module_testmodule_master_20170109091357',
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
def on_tag_artifacts_cb(cls, artifacts):
self.assertEqual(tag_groups.pop(0), set(artifacts))
@@ -728,8 +730,9 @@ class TestBuild(unittest.TestCase):
buildtag_groups = []
buildtag_groups.append(set(
['perl-Tangerine-0.23-1.module_testmodule_master_20170109091357',
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
'perl-List-Compare-0.53-5.module_testmodule_master_20170109091357',
'tangerine-0.22-3.module_testmodule_master_20170109091357']))
def on_buildroot_add_artifacts_cb(cls, artifacts, install):
self.assertEqual(buildtag_groups.pop(0), set(artifacts))
TestModuleBuilder.on_buildroot_add_artifacts_cb = on_buildroot_add_artifacts_cb
@@ -742,7 +745,7 @@ class TestBuild(unittest.TestCase):
# or "ready" state.
for build in models.ComponentBuild.query.filter_by(module_id=2).all():
self.assertEqual(build.state, koji.BUILD_STATES['COMPLETE'])
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]] )
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]])
self.assertNotEqual(build.package, "module-build-macros")
@timed(60)
@@ -769,7 +772,7 @@ class TestBuild(unittest.TestCase):
# Set the components from batch 2 to COMPLETE
components = models.ComponentBuild.query.filter_by(module_id=module_build_id)
for c in components:
print c
print(c)
if c.batch == 2:
c.state = koji.BUILD_STATES["COMPLETE"]
db.session.commit()
@@ -783,4 +786,4 @@ class TestBuild(unittest.TestCase):
# or "ready" state.
for build in models.ComponentBuild.query.filter_by(module_id=module_build_id).all():
self.assertEqual(build.state, koji.BUILD_STATES['COMPLETE'])
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]] )
self.assertTrue(build.module_build.state in [models.BUILD_STATES["done"], models.BUILD_STATES["ready"]])

View File

@@ -36,6 +36,7 @@ from tests import conf, init_data
from module_build_service.builder import KojiModuleBuilder
class FakeKojiModuleBuilder(KojiModuleBuilder):
@module_build_service.utils.retry(wait_on=(xmlrpclib.ProtocolError, koji.GenericError))
@@ -50,6 +51,7 @@ class FakeKojiModuleBuilder(KojiModuleBuilder):
return koji_session
class TestKojiBuilder(unittest.TestCase):
def setUp(self):
@@ -234,4 +236,3 @@ class TestGetKojiClientSession(unittest.TestCase):
components=[])
args, kwargs = mocked_krb_login.call_args
self.assertTrue(set([('proxyuser', self.module.owner)]).issubset(set(kwargs.items())))

View File

@@ -20,16 +20,12 @@
#
# Written by Jan Kaluza <jkaluza@redhat.com>
from nose.tools import raises, eq_
import unittest
import mock
import os.path
from mock import patch
from module_build_service import conf
class TestConfig(unittest.TestCase):
def test_path_expanduser(self):
test_dir = "~/modulebuild/builds"

View File

@@ -28,10 +28,8 @@ import os
from os import path
from os.path import dirname
import module_build_service.messaging
import module_build_service.scheduler.handlers.repos
import module_build_service.utils
from module_build_service import models, conf, build_logs
from mock import patch, Mock
@@ -60,7 +58,6 @@ class TestBuild(unittest.TestCase):
self.vcr = vcr.use_cassette(filename)
self.vcr.__enter__()
def tearDown(self):
# Necessary to restart the twisted reactor for the next test.
import sys
@@ -88,8 +85,8 @@ class TestBuild(unittest.TestCase):
pkg_res.return_value = Mock()
pkg_res.return_value.version = "current-tested-version"
rpm_mock = Mock()
rpm_out = "rpm-name;1.0;r1;x86_64;(none);sigmd5:1;sigpgp:p;siggpg:g\n" \
"rpm-name-2;2.0;r2;i686;1;sigmd5:2;sigpgp:p2;siggpg:g2"
rpm_out = "rpm-name;1.0;r1;x86_64;(none);sigmd5:1;sigpgp:p;siggpg:g\n" \
"rpm-name-2;2.0;r2;i686;1;sigmd5:2;sigpgp:p2;siggpg:g2"
attrs = {'communicate.return_value': (rpm_out, 'error'),
'wait.return_value': 0}
rpm_mock.configure_mock(**attrs)
@@ -127,8 +124,8 @@ class TestBuild(unittest.TestCase):
pkg_res.return_value = Mock()
pkg_res.return_value.version = "current-tested-version"
rpm_mock = Mock()
rpm_out = "rpm-name;1.0;r1;x86_64;(none);sigmd5:1;sigpgp:p;siggpg:g\n" \
"rpm-name-2;2.0;r2;i686;1;sigmd5:2;sigpgp:p2;siggpg:g2"
rpm_out = "rpm-name;1.0;r1;x86_64;(none);sigmd5:1;sigpgp:p;siggpg:g\n" \
"rpm-name-2;2.0;r2;i686;1;sigmd5:2;sigpgp:p2;siggpg:g2"
attrs = {'communicate.return_value': (rpm_out, 'error'),
'wait.return_value': 0}
rpm_mock.configure_mock(**attrs)
@@ -149,7 +146,6 @@ class TestBuild(unittest.TestCase):
rpms_in_tag.assert_called_once()
self.assertEqual(expected_output, ret)
def test_prepare_file_directory(self):
""" Test preparation of directory with output files """
dir_path = self.cg._prepare_file_directory()

View File

@@ -29,7 +29,6 @@ import unittest
from module_build_service import log
from module_build_service.logger import ModuleBuildLogs
from module_build_service.scheduler.consumer import MBSConsumer
from mock import patch, PropertyMock
class TestLogger(unittest.TestCase):

View File

@@ -22,7 +22,7 @@
import unittest
from module_build_service import messaging, conf
from module_build_service import messaging
from mock import patch, PropertyMock
@@ -55,7 +55,7 @@ class TestFedmsgMessaging(unittest.TestCase):
self.assertEqual(msg.build_new_state, 1)
@patch("module_build_service.config.Config.system",
new_callable=PropertyMock, return_value="copr")
new_callable=PropertyMock, return_value="copr")
def test_copr_build_end(self, conf_system):
# http://fedora-fedmsg.readthedocs.io/en/latest/topics.html#copr-build-end
copr_build_end_msg = {
@@ -116,7 +116,6 @@ class TestFedmsgMessaging(unittest.TestCase):
self.assertEqual(msg.tag, "module-debugging-tools-master-20170405115403-build")
self.assertEqual(msg.artifact, "module-build-macros")
def test_buildsys_repo_done(self):
# https://fedora-fedmsg.readthedocs.io/en/latest/topics.html#id134
buildsys_tag_msg = {

View File

@@ -34,6 +34,7 @@ import modulemd
base_dir = os.path.dirname(__file__)
cassette_dir = base_dir + '/vcr-request-data/'
class TestPDCModule(unittest.TestCase):
def setUp(self):
@@ -111,5 +112,5 @@ class TestPDCModule(unittest.TestCase):
set(['shadow-utils', 'redhat-rpm-config', 'rpm-build',
'fedora-modular-release', 'fedpkg-minimal', 'gnupg2',
'bash'])
}
}
self.assertEqual(result, expected)

View File

@@ -30,7 +30,7 @@ import os
import vcr
import koji
from tests import conf, db, app, scheduler_init_data
from module_build_service import conf, build_logs
from module_build_service import build_logs
base_dir = os.path.dirname(os.path.dirname(__file__))
cassette_dir = base_dir + '/vcr-request-data/'
@@ -85,11 +85,11 @@ class TestModuleWait(unittest.TestCase):
from_module_event.return_value = mocked_module_build
msg = module_build_service.messaging.MBSModule(msg_id=None, module_build_id=1,
module_build_state='some state')
module_build_state='some state')
self.fn(config=self.config, session=self.session, msg=msg)
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={'build': [], 'srpm-build': []})
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.builder.KojiModuleBuilder.get_session")
@patch("module_build_service.builder.GenericBuilder.create_from_module")
@patch('module_build_service.pdc')
@@ -113,13 +113,13 @@ class TestModuleWait(unittest.TestCase):
create_builder.return_value = builder
msg = module_build_service.messaging.MBSModule(msg_id=None, module_build_id=1,
module_build_state='some state')
module_build_state='some state')
module_build_service.scheduler.handlers.modules.wait(
config=conf, session=db.session, msg=msg)
koji_session.newRepo.assert_called_once_with("module-123-build")
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={'build': [], 'srpm-build': []})
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.builder.KojiModuleBuilder.get_session")
@patch("module_build_service.builder.GenericBuilder.create_from_module")
@patch('module_build_service.pdc')
@@ -143,7 +143,7 @@ class TestModuleWait(unittest.TestCase):
create_builder.return_value = builder
msg = module_build_service.messaging.MBSModule(msg_id=None, module_build_id=1,
module_build_state='some state')
module_build_state='some state')
module_build_service.scheduler.handlers.modules.wait(
config=conf, session=db.session, msg=msg)
self.assertTrue(not koji_session.newRepo.called)

View File

@@ -20,19 +20,11 @@
import unittest
from os import path
import vcr
import modulemd
from mock import patch
import module_build_service.utils
import module_build_service.scm
from module_build_service import models, conf
from module_build_service.errors import ProgrammingError, ValidationError
from tests import test_reuse_component_init_data, init_data, db
import mock
from mock import PropertyMock
import koji
import module_build_service.scheduler.handlers.components
from module_build_service.builder import GenericBuilder, KojiModuleBuilder
from module_build_service.scheduler.producer import MBSProducer
import six.moves.queue as queue
from datetime import datetime, timedelta
@@ -41,6 +33,7 @@ BASE_DIR = path.abspath(path.dirname(__file__))
CASSETTES_DIR = path.join(
path.abspath(path.dirname(__file__)), '..', 'vcr-request-data')
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.scheduler.consumer.get_global_consumer")
@@ -123,10 +116,9 @@ class TestPoller(unittest.TestCase):
koji_session.newRepo.assert_called_once_with("module-testmodule-build")
def test_trigger_new_repo_when_succeded(self, create_builder,
koji_get_session, global_consumer,
dbg):
koji_get_session, global_consumer,
dbg):
"""
Tests that we do not call koji_sesion.newRepo when newRepo task
succeeded.

View File

@@ -34,6 +34,7 @@ from tests import conf, db, app
base_dir = dirname(dirname(__file__))
cassette_dir = base_dir + '/vcr-request-data/'
class TestRepoDone(unittest.TestCase):
def setUp(self):

View File

@@ -20,10 +20,8 @@
#
# Written by Jan Kaluza <jkaluza@redhat.com>
from os.path import dirname
import unittest
import mock
import vcr
from mock import patch
@@ -31,10 +29,11 @@ import module_build_service.messaging
import module_build_service.scheduler.handlers.repos
import module_build_service.models
from tests import test_reuse_component_init_data
from tests import conf, db, app
from tests import conf, db
import koji
class TestTagTagged(unittest.TestCase):
def setUp(self):
@@ -63,9 +62,8 @@ class TestTagTagged(unittest.TestCase):
module_build_service.scheduler.handlers.tags.tagged(
config=conf, session=db.session, msg=msg)
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={'build': [], 'srpm-build': []})
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.builder.KojiModuleBuilder.get_session")
@patch("module_build_service.builder.GenericBuilder.create_from_module")
def test_newrepo(self, create_builder, koji_get_session, dbg):
@@ -123,9 +121,8 @@ class TestTagTagged(unittest.TestCase):
# status later in poller.
self.assertEqual(module_build.new_repo_task_id, 123456)
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={'build': [], 'srpm-build': []})
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.builder.KojiModuleBuilder.get_session")
@patch("module_build_service.builder.GenericBuilder.create_from_module")
def test_newrepo_still_building_components(self, create_builder, koji_get_session, dbg):
@@ -161,7 +158,7 @@ class TestTagTagged(unittest.TestCase):
self.assertTrue(not koji_session.newRepo.called)
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value={'build': [], 'srpm-build': []})
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.builder.KojiModuleBuilder.get_session")
@patch("module_build_service.builder.GenericBuilder.create_from_module")
def test_newrepo_failed_components(self, create_builder, koji_get_session, dbg):
@@ -215,7 +212,7 @@ class TestTagTagged(unittest.TestCase):
self.assertEqual(module_build.new_repo_task_id, 123456)
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
return_value = {'build': [], 'srpm-build': []})
return_value={'build': [], 'srpm-build': []})
@patch("module_build_service.builder.KojiModuleBuilder.get_session")
@patch("module_build_service.builder.GenericBuilder.create_from_module")
def test_newrepo_multiple_batches_tagged(

View File

@@ -31,7 +31,6 @@ from module_build_service.errors import ProgrammingError, ValidationError
from tests import (test_reuse_component_init_data, init_data, db,
test_reuse_shared_userspace_init_data)
import mock
from mock import PropertyMock
import koji
import module_build_service.scheduler.handlers.components
from module_build_service.builder import GenericBuilder, KojiModuleBuilder
@@ -41,6 +40,7 @@ BASE_DIR = path.abspath(path.dirname(__file__))
CASSETTES_DIR = path.join(
path.abspath(path.dirname(__file__)), '..', 'vcr-request-data')
class MockedSCM(object):
def __init__(self, mocked_scm, name, mmd_filename, commit=None):
self.mocked_scm = mocked_scm
@@ -60,13 +60,14 @@ class MockedSCM(object):
mkdir(scm_dir)
base_dir = path.abspath(path.dirname(__file__))
copyfile(path.join(base_dir, '..', 'staged_data', self.mmd_filename),
path.join(scm_dir, self.name + ".yaml"))
path.join(scm_dir, self.name + ".yaml"))
return scm_dir
def get_latest(self, branch='master'):
return self.commit if self.commit else branch
class TestUtils(unittest.TestCase):
def setUp(self):
@@ -115,8 +116,8 @@ class TestUtils(unittest.TestCase):
'stream': 'master',
'version': '20170404161234'}},
'rpms': {'perl-List-Compare': {'ref': '76f9d8c8e87eed0aab91034b01d3d5ff6bd5b4cb'},
'perl-Tangerine': {'ref': '4ceea43add2366d8b8c5a622a2fb563b625b9abf'},
'tangerine': {'ref': 'fbed359411a1baa08d4a88e0d12d426fbf8f602c'}},
'perl-Tangerine': {'ref': '4ceea43add2366d8b8c5a622a2fb563b625b9abf'},
'tangerine': {'ref': 'fbed359411a1baa08d4a88e0d12d426fbf8f602c'}},
'scmurl': 'git://pkgs.stg.fedoraproject.org/modules/testmodule'
'.git?#620ec77321b2ea7b0d67d82992dda3e1d67055b4',
}
@@ -133,6 +134,7 @@ class TestUtils(unittest.TestCase):
'f24': '4ceea43add2366d8b8c5a622a2fb563b625b9abf',
'f23': 'fbed359411a1baa08d4a88e0d12d426fbf8f602c',
'f25': '76f9d8c8e87eed0aab91034b01d3d5ff6bd5b4cb'}
def mocked_get_latest(branch="master"):
return hashes_returned[branch]
mocked_scm.return_value.get_latest = mocked_get_latest
@@ -152,8 +154,8 @@ class TestUtils(unittest.TestCase):
'stream': 'master',
'version': '20170404161234'}},
'rpms': {'perl-List-Compare': {'ref': '76f9d8c8e87eed0aab91034b01d3d5ff6bd5b4cb'},
'perl-Tangerine': {'ref': '4ceea43add2366d8b8c5a622a2fb563b625b9abf'},
'tangerine': {'ref': 'fbed359411a1baa08d4a88e0d12d426fbf8f602c'}},
'perl-Tangerine': {'ref': '4ceea43add2366d8b8c5a622a2fb563b625b9abf'},
'tangerine': {'ref': 'fbed359411a1baa08d4a88e0d12d426fbf8f602c'}},
'scmurl': None,
}
}
@@ -368,7 +370,7 @@ class TestUtils(unittest.TestCase):
self.assertEquals(
validate_koji_tag_good_tag_value_in_dict_nondefault_key(
{'nondefault': 'module-foo'}), True)
{'nondefault': 'module-foo'}), True)
def test_validate_koji_tag_double_trouble_good(self):
""" Test that we pass on a list of tags that are good. """
@@ -413,7 +415,7 @@ class TestUtils(unittest.TestCase):
component states properly.
"""
MockedSCM(mocked_scm, 'testmodule', 'testmodule.yaml',
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
with app.app_context():
test_reuse_component_init_data()
# Mark the module build as failed, so we can resubmit it.
@@ -502,7 +504,6 @@ class DummyModuleBuilder(GenericBuilder):
self.tag_name = tag_name
self.config = config
def buildroot_connect(self, groups):
pass
@@ -548,6 +549,7 @@ class DummyModuleBuilder(GenericBuilder):
def list_tasks_for_components(self, component_builds=None, state='active'):
pass
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups", return_value={'build': [], 'srpm-build': []})
class TestBatches(unittest.TestCase):
@@ -639,9 +641,6 @@ class TestBatches(unittest.TestCase):
builder = mock.MagicMock()
builder.buildroot_ready.return_value = False
further_work = module_build_service.utils.start_next_batch_build(
conf, module_build, db.session, builder)
# Batch number should not increase.
self.assertEqual(module_build.batch, 1)

View File

@@ -28,7 +28,7 @@ import vcr
import modulemd as _modulemd
import module_build_service.scm
from mock import patch, Mock, PropertyMock, MagicMock
from mock import patch, PropertyMock, MagicMock
from shutil import copyfile
from os import path, mkdir
from os.path import dirname
@@ -96,7 +96,7 @@ class MockedSCM(object):
mkdir(scm_dir)
base_dir = path.abspath(path.dirname(__file__))
copyfile(path.join(base_dir, '..', 'staged_data', mmd_filename),
path.join(scm_dir, self.name + ".yaml"))
path.join(scm_dir, self.name + ".yaml"))
self.checkout_id += 1
@@ -258,7 +258,7 @@ class TestViews(unittest.TestCase):
def test_query_builds_filter_task_id(self):
rv = self.client.get('/module-build-service/1/component-builds/?task_id=12312346')
data = json.loads(rv.data)
self.assertEquals(data['meta']['total'], 1)
self.assertEquals(data['meta']['total'], 1)
def test_query_builds_filter_name(self):
rv = self.client.get('/module-build-service/1/module-builds/?name=nginx')
@@ -335,7 +335,7 @@ class TestViews(unittest.TestCase):
def test_query_builds_order_by(self):
rv = self.client.get('/module-build-service/1/module-builds/?'
'per_page=10&order_by=id')
'per_page=10&order_by=id')
items = json.loads(rv.data)['items']
# Check that the id is 1, 2, 3, ..., 10
for idx, item in enumerate(items):
@@ -343,7 +343,7 @@ class TestViews(unittest.TestCase):
def test_query_builds_order_desc_by(self):
rv = self.client.get('/module-build-service/1/module-builds/?'
'per_page=10&order_desc_by=id')
'per_page=10&order_desc_by=id')
items = json.loads(rv.data)['items']
# Check that the id is items[0]["id"], items[0]["id"] - 1, ...
for idx, item in enumerate(items):
@@ -355,7 +355,7 @@ class TestViews(unittest.TestCase):
we prefer order_desc_by.
"""
rv = self.client.get('/module-build-service/1/module-builds/?'
'per_page=10&order_desc_by=id&order_by=name')
'per_page=10&order_desc_by=id&order_by=name')
items = json.loads(rv.data)['items']
# Check that the id is items[0]["id"], items[0]["id"] - 1, ...
for idx, item in enumerate(items):
@@ -363,7 +363,7 @@ class TestViews(unittest.TestCase):
def test_query_builds_order_by_wrong_key(self):
rv = self.client.get('/module-build-service/1/module-builds/?'
'per_page=10&order_by=unknown')
'per_page=10&order_by=unknown')
data = json.loads(rv.data)
self.assertEquals(data['status'], 400)
self.assertEquals(data['error'], 'Bad Request')
@@ -472,7 +472,7 @@ class TestViews(unittest.TestCase):
{'branch': 'master', 'scmurl': 'git://badurl.com'}))
data = json.loads(rv.data)
self.assertEquals(data['message'], 'The submitted scmurl '
'git://badurl.com is not allowed')
'git://badurl.com is not allowed')
self.assertEquals(data['status'], 403)
self.assertEquals(data['error'], 'Forbidden')
@@ -483,15 +483,15 @@ class TestViews(unittest.TestCase):
'testmodule.git'}))
data = json.loads(rv.data)
self.assertEquals(data['message'], 'The submitted scmurl '
'git://pkgs.stg.fedoraproject.org/modules/testmodule.git '
'is not valid')
'git://pkgs.stg.fedoraproject.org/modules/testmodule.git '
'is not valid')
self.assertEquals(data['status'], 403)
self.assertEquals(data['error'], 'Forbidden')
@patch('module_build_service.auth.get_user', return_value=user)
@patch('module_build_service.scm.SCM')
def test_submit_build_bad_modulemd(self, mocked_scm, mocked_get_user):
mocked_scm_obj = MockedSCM(mocked_scm, "bad", "bad.yaml")
MockedSCM(mocked_scm, "bad", "bad.yaml")
rv = self.client.post('/module-build-service/1/module-builds/', data=json.dumps(
{'branch': 'master', 'scmurl': 'git://pkgs.stg.fedoraproject.org/modules/'
@@ -562,8 +562,9 @@ class TestViews(unittest.TestCase):
@patch("module_build_service.config.Config.modules_allow_repository",
new_callable=PropertyMock, return_value=True)
def test_submit_build_includedmodule(self, conf, mocked_scm, mocked_get_user):
mocked_scm_obj = MockedSCM(mocked_scm, "includedmodules",
["includedmodules.yaml", "testmodule.yaml"])
MockedSCM(mocked_scm, "includedmodules", ["includedmodules.yaml",
"testmodule.yaml"])
rv = self.client.post('/module-build-service/1/module-builds/', data=json.dumps(
{'branch': 'master', 'scmurl': 'git://pkgs.stg.fedoraproject.org/modules/'
'testmodule.git?#68931c90de214d9d13feefbd35246a81b6cb8d49'}))
@@ -609,9 +610,9 @@ class TestViews(unittest.TestCase):
@patch('module_build_service.auth.get_user', return_value=user)
@patch('module_build_service.scm.SCM')
def test_submit_build_includedmodule_custom_repo_not_allowed(self,
mocked_scm, mocked_get_user):
mocked_scm_obj = MockedSCM(mocked_scm, "includedmodules",
["includedmodules.yaml", "testmodule.yaml"])
mocked_scm, mocked_get_user):
MockedSCM(mocked_scm, "includedmodules", ["includedmodules.yaml",
"testmodule.yaml"])
rv = self.client.post('/module-build-service/1/module-builds/', data=json.dumps(
{'branch': 'master', 'scmurl': 'git://pkgs.stg.fedoraproject.org/modules/'
'testmodule.git?#68931c90de214d9d13feefbd35246a81b6cb8d49'}))
@@ -651,9 +652,9 @@ class TestViews(unittest.TestCase):
return_value=('sammy', set(["packager", "mbs-admin"])))
def test_cancel_build_admin(self, mocked_get_user):
with patch("module_build_service.config.Config.admin_groups",
new_callable=PropertyMock, return_value=set(["mbs-admin"])):
new_callable=PropertyMock, return_value=set(["mbs-admin"])):
rv = self.client.patch('/module-build-service/1/module-builds/30',
data=json.dumps({'state': 'failed'}))
data=json.dumps({'state': 'failed'}))
data = json.loads(rv.data)
self.assertEquals(data['state'], 4)
@@ -663,9 +664,9 @@ class TestViews(unittest.TestCase):
return_value=('sammy', set(["packager"])))
def test_cancel_build_no_admin(self, mocked_get_user):
with patch("module_build_service.config.Config.admin_groups",
new_callable=PropertyMock, return_value=set(["mbs-admin"])):
new_callable=PropertyMock, return_value=set(["mbs-admin"])):
rv = self.client.patch('/module-build-service/1/module-builds/30',
data=json.dumps({'state': 'failed'}))
data=json.dumps({'state': 'failed'}))
data = json.loads(rv.data)
self.assertEquals(data['status'], 403)
@@ -861,7 +862,7 @@ class TestViews(unittest.TestCase):
def submit(scmurl):
return self.client.post('/module-build-service/1/module-builds/', data=json.dumps(
{'branch': 'master', 'scmurl': scmurl}))
{'branch': 'master', 'scmurl': scmurl}))
allow_custom_scmurls.return_value = False
res1 = submit('git://some.custom.url.org/modules/testmodule.git?#68931c9')