def listSideTags(basetag=None, user=None, queryOpts=None): """List all sidetags with additional filters :param basetag: filter by basteag id or name :type basetag: int or str :param user: filter by userid or username :type user: int or str :param queryOpts: additional query options {countOnly, order, offset, limit} :type queryOpts: dict :returns: list of dicts: id, name, user_id, user_name """ # te1.sidetag # te2.user_id # te3.basetag if user is not None: user_id = str(get_user(user, strict=True)["id"]) else: user_id = None if basetag is not None: basetag_id = get_tag(basetag, strict=True)["id"] else: basetag_id = None joins = [ "LEFT JOIN tag_extra AS te1 ON tag.id = te1.tag_id", "LEFT JOIN tag_extra AS te2 ON tag.id = te2.tag_id", "LEFT JOIN users ON CAST(te2.value AS INTEGER) = users.id", ] clauses = [ "te1.active IS TRUE", "te1.key = 'sidetag'", "te1.value = 'true'", "te2.active IS TRUE", "te2.key = 'sidetag_user_id'" ] if user_id: clauses.append("te2.value = %(user_id)s") if basetag_id: joins.append("LEFT JOIN tag_inheritance ON tag.id = tag_inheritance.tag_id") clauses.extend( [ "tag_inheritance.active IS TRUE", "tag_inheritance.parent_id = %(basetag_id)s", ] ) query = QueryProcessor( tables=["tag"], clauses=clauses, columns=["tag.id", "tag.name", "te2.value", "users.name"], aliases=["id", "name", "user_id", "user_name"], joins=joins, values={"basetag_id": basetag_id, "user_id": user_id}, opts=queryOpts, ) return query.execute()
def createSideTag(basetag, debuginfo=False): """Create a side tag. :param basetag: name or ID of base tag :type basetag: str or int :param debuginfo: should buildroot repos contain debuginfo? :type debuginfo: bool """ # Any logged-in user is able to request creation of side tags, # as long the request meets the policy. context.session.assertLogin() user = get_user(context.session.user_id, strict=True) basetag = get_tag(basetag, strict=True) query = QueryProcessor( tables=["tag_extra"], clauses=[ "key='sidetag_user_id'", "value=%(user_id)s", "active IS TRUE" ], columns=["COUNT(*)"], aliases=["user_tags"], values={"user_id": str(user["id"])}, ) user_tags = query.executeOne() if user_tags is None: # should not ever happen raise koji.GenericError("Unknown db error") # Policy is a very flexible mechanism, that can restrict for which # tags sidetags can be created, or which users can create sidetags etc. assert_policy("sidetag", { "tag": basetag["id"], "number_of_tags": user_tags["user_tags"] }) # ugly, it will waste one number in tag_id_seq, but result will match with # id assigned by _create_tag tag_id = nextval("tag_id_seq") + 1 sidetag_name = "%s-side-%s" % (basetag["name"], tag_id) extra = { "sidetag": True, "sidetag_user": user["name"], "sidetag_user_id": user["id"], } if debuginfo: extra['with_debuginfo'] = True sidetag_id = _create_tag( sidetag_name, parent=basetag["id"], arches=basetag["arches"], extra=extra, ) _create_build_target(sidetag_name, sidetag_id, sidetag_id) return {"name": sidetag_name, "id": sidetag_id}
def editSideTag(sidetag, debuginfo=None, rpm_macros=None, remove_rpm_macros=None): """Restricted ability to modify sidetags, parent tag must have: sidetag_debuginfo_allowed: 1 sidetag_rpm_macros_allowed: 1 in extra, if modifying functions should work. For blocking/unblocking further policy must be compatible with these operations. :param sidetag: sidetag id or name :type sidetag: int or str :param debuginfo: set or disable debuginfo repo generation :type debuginfo: bool :param rpm_macros: add/update rpms macros in extra :type rpm_macros: dict :param remove_rpm_macros: remove rpm macros from extra :type remove_rpm_macros: list of str """ context.session.assertLogin() user = get_user(context.session.user_id, strict=True) sidetag = get_tag(sidetag, strict=True) # sanity/access is_sidetag(sidetag, raise_error=True) is_sidetag_owner(sidetag, user, raise_error=True) parent_id = readInheritanceData(sidetag['id'])[0]['parent_id'] parent = get_tag(parent_id) if debuginfo is not None and not parent['extra'].get( 'sidetag_debuginfo_allowed'): raise koji.GenericError( "Debuginfo setting is not allowed in parent tag.") if (rpm_macros is not None or remove_rpm_macros is not None) \ and not parent['extra'].get('sidetag_rpm_macros_allowed'): raise koji.GenericError( "RPM macros change is not allowed in parent tag.") kwargs = {'extra': {}} if debuginfo is not None: kwargs['extra']['with_debuginfo'] = bool(debuginfo) if rpm_macros is not None: for macro, value in rpm_macros.items(): kwargs['extra']['rpm.macro.%s' % macro] = value if remove_rpm_macros is not None: kwargs['remove_extra'] = [ 'rpm.macro.%s' % m for m in remove_rpm_macros ] _edit_tag(sidetag['id'], **kwargs)
def removeSideTag(sidetag): """Remove a side tag :param sidetag: id or name of sidetag :type sidetag: int or str """ context.session.assertLogin() user = get_user(context.session.user_id, strict=True) sidetag = get_tag(sidetag, strict=True) # sanity/access is_sidetag(sidetag, raise_error=True) is_sidetag_owner(sidetag, user, raise_error=True) _remove_sidetag(sidetag)
def get_message_body(topic, *args, **kws): msg = {} if topic == 'package.list.change': msg['tag'] = kws['tag']['name'] msg['package'] = kws['package']['name'] elif topic == 'task.state.change': msg['method'] = kws['info']['method'] msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['owner'] = kojihub.get_user(kws['info']['owner'])['name'] msg['id'] = kws['info']['id'] elif topic == 'build.state.change': info = kws['info'] msg['name'] = info['name'] msg['version'] = info['version'] msg['release'] = info['release'] msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] elif topic == 'import': msg['type'] = kws['type'] elif topic in ('tag', 'untag'): msg['tag'] = kws['tag']['name'] build = kws['build'] msg['name'] = build['name'] msg['version'] = build['version'] msg['release'] = build['release'] msg['user'] = kws['user']['name'] elif topic == 'repo.init': msg['tag'] = kws['tag']['name'] elif topic == 'repo.done': msg['tag'] = kws['repo']['tag_name'] return msg
def get_message_body(topic, *args, **kws): msg = {} if topic == 'package.list.change': msg['tag'] = kws['tag']['name'] msg['package'] = kws['package']['name'] elif topic == 'task.state.change': info = kws['info'] # Stuff in information about descendant tasks task = kojihub.Task(info['id']) info['children'] = task.getChildren() # Send the whole info dict along because it might have useful info. # For instance, it contains the mention of what format createAppliance # is using (raw or qcow2). msg['info'] = info msg['method'] = kws['info']['method'] msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['id'] = kws['info']['id'] # extract a useful identifier from the request string request = kws.get('info', {}).get('request', ['/']) msg['srpm'] = request[0].split('/')[-1] if 'owner_name' in info: msg['owner'] = info['owner_name'] elif 'owner_id' in info: msg['owner'] = kojihub.get_user(info['owner_id'])['name'] elif 'owner' in info: msg['owner'] = kojihub.get_user(info['owner'])['name'] else: msg['owner'] = None elif topic == 'build.state.change': info = kws['info'] msg['name'] = info['name'] msg['version'] = info['version'] msg['release'] = info['release'] msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['build_id'] = info.get('id', None) msg['task_id'] = info.get('task_id', None) if msg['task_id']: task = kojihub.Task(msg['task_id']) msg['request'] = task.getRequest() else: msg['request'] = None if 'owner_name' in info: msg['owner'] = info['owner_name'] elif 'owner_id' in info: msg['owner'] = kojihub.get_user(info['owner_id'])['name'] elif 'owner' in info: msg['owner'] = kojihub.get_user(info['owner'])['name'] else: msg['owner'] = None elif topic == 'import': # TODO -- import is currently unused. # Should we remove it? msg['type'] = kws['type'] elif topic in ('tag', 'untag'): msg['tag'] = kws['tag']['name'] build = kws['build'] msg['name'] = build['name'] msg['version'] = build['version'] msg['release'] = build['release'] msg['user'] = kws['user']['name'] msg['owner'] = kojihub.get_user(kws['build']['owner_id'])['name'] msg['tag_id'] = kws['tag']['id'] msg['build_id'] = kws['build']['id'] elif topic == 'repo.init': msg['tag'] = kws['tag']['name'] msg['tag_id'] = kws['tag']['id'] msg['repo_id'] = kws['repo_id'] elif topic == 'repo.done': msg['tag'] = kws['repo']['tag_name'] msg['tag_id'] = kws['repo']['tag_id'] msg['repo_id'] = kws['repo']['id'] elif topic == 'rpm.sign': if 'attribute' in kws: # v1.10.1 and earlier msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['info'] = kws['info'] else: # v1.11.0 (and maybe higher, but who knows) msg['sigkey'] = kws['sigkey'] msg['sighash'] = kws['sighash'] msg['build'] = kws['build'] msg['rpm'] = kws['rpm'] return msg
def get_message_body(topic, *args, **kws): msg = {} if topic == 'package.list.change': msg['tag'] = kws['tag']['name'] msg['package'] = kws['package']['name'] msg['action'] = kws['action'] if 'owner' in kws: msg['owner'] = kojihub.get_user(kws['owner'])['name'] else: msg['owner'] = None msg['block'] = kws.get('block', None) msg['extra_arches'] = kws.get('extra_arches', None) msg['force'] = kws.get('force', None) msg['update'] = kws.get('update', None) elif topic == 'task.state.change': info = kws['info'] # Stuff in information about descendant tasks task = kojihub.Task(info['id']) info['children'] = task.getChildren() # Send the whole info dict along because it might have useful info. # For instance, it contains the mention of what format createAppliance # is using (raw or qcow2). msg['info'] = info msg['method'] = kws['info']['method'] msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['id'] = kws['info']['id'] # extract a useful identifier from the request string request = kws.get('info', {}).get('request', ['/']) msg['srpm'] = request[0].split('/')[-1] if 'owner_name' in info: msg['owner'] = info['owner_name'] elif 'owner_id' in info: msg['owner'] = kojihub.get_user(info['owner_id'])['name'] elif 'owner' in info: msg['owner'] = kojihub.get_user(info['owner'])['name'] else: msg['owner'] = None elif topic == 'build.state.change': info = kws['info'] msg['name'] = info['name'] msg['version'] = info['version'] msg['release'] = info['release'] msg['epoch'] = info.get('epoch') msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['build_id'] = info.get('id', None) msg['task_id'] = info.get('task_id', None) if msg['task_id']: task = kojihub.Task(msg['task_id']) msg['request'] = task.getRequest() else: msg['request'] = None if 'owner_name' in info: msg['owner'] = info['owner_name'] elif 'owner_id' in info: msg['owner'] = kojihub.get_user(info['owner_id'])['name'] elif 'owner' in info: msg['owner'] = kojihub.get_user(info['owner'])['name'] else: msg['owner'] = None elif topic == 'import': # TODO -- import is currently unused. # Should we remove it? msg['type'] = kws['type'] elif topic in ('tag', 'untag'): msg['tag'] = kws['tag']['name'] build = kws['build'] msg['name'] = build['name'] msg['version'] = build['version'] msg['release'] = build['release'] msg['user'] = kws['user']['name'] msg['owner'] = kojihub.get_user(kws['build']['owner_id'])['name'] msg['tag_id'] = kws['tag']['id'] msg['build_id'] = kws['build']['id'] elif topic == 'repo.init': msg['tag'] = kws['tag']['name'] msg['tag_id'] = kws['tag']['id'] msg['repo_id'] = kws['repo_id'] elif topic == 'repo.done': msg['tag'] = kws['repo']['tag_name'] msg['tag_id'] = kws['repo']['tag_id'] msg['repo_id'] = kws['repo']['id'] elif topic == 'rpm.sign': if 'attribute' in kws: # v1.10.1 and earlier msg['attribute'] = kws['attribute'] msg['old'] = kws['old'] msg['new'] = kws['new'] msg['info'] = kws['info'] else: # v1.11.0 (and maybe higher, but who knows) msg['sigkey'] = kws['sigkey'] msg['sighash'] = kws['sighash'] msg['build'] = kws['build'] msg['rpm'] = kws['rpm'] return msg
def createSideTag(basetag, debuginfo=False, suffix=None): """Create a side tag. :param basetag: name or ID of base tag :type basetag: str or int :param debuginfo: should buildroot repos contain debuginfo? :type debuginfo: bool :param suffix: suffix which will be appended to generated sidetag name List of allowed suffixes needs to be defined in config. :type suffix: str :returns dict: sidetag name + id """ if suffix and suffix not in ALLOWED_SUFFIXES: raise koji.GenericError("%s suffix is not allowed for sidetag" % suffix) # Any logged-in user is able to request creation of side tags, # as long the request meets the policy. context.session.assertLogin() user = get_user(context.session.user_id, strict=True) basetag = get_tag(basetag, strict=True) query = QueryProcessor( tables=["tag_extra"], clauses=["key='sidetag_user_id'", "value=%(user_id)s", "active IS TRUE"], columns=["COUNT(*)"], aliases=["user_tags"], values={"user_id": str(user["id"])}, ) user_tags = query.executeOne() if user_tags is None: # should not ever happen raise koji.GenericError("Unknown db error") # Policy is a very flexible mechanism, that can restrict for which # tags sidetags can be created, or which users can create sidetags etc. assert_policy( "sidetag", {"tag": basetag["id"], "number_of_tags": user_tags["user_tags"]} ) # ugly, it will waste one number in tag_id_seq, but result will match with # id assigned by _create_tag tag_id = nextval("tag_id_seq") + 1 sidetag_name = NAME_TEMPLATE.format(basetag=basetag["name"], tag_id=tag_id) if suffix: sidetag_name += '-%s' % suffix extra = { "sidetag": True, "sidetag_user": user["name"], "sidetag_user_id": user["id"], } if debuginfo: extra['with_debuginfo'] = True sidetag_id = _create_tag( sidetag_name, parent=basetag["id"], arches=basetag["arches"], extra=extra, ) _create_build_target(sidetag_name, sidetag_id, sidetag_id) return {"name": sidetag_name, "id": sidetag_id}