Esempio n. 1
0
    def test_send_via_fedora_messaging(self, Message, publish):
        messaging.publish('build.tagged', {'build_id': 1})

        Message.assert_called_once_with(topic='build.tagged',
                                        body={'build_id': 1})

        outgoing_msg = Message.return_value
        publish.assert_called_once_with(outgoing_msg)
def handle(rule_defs, event_msg):
    this_name = event_msg["name"]
    this_stream = event_msg["stream"]
    this_version = event_msg["version"]
    this_context = event_msg["context"]
    nsvc = f"{this_name}-{this_stream}-{this_version}-{this_context}"

    try:
        modulemd = yaml.safe_load(retrieve_modulemd_content(event_msg['id']))
    except requests.exceptions.HTTPError as e:
        logger.exception(f'Failed to retrieve modulemd for {nsvc}: {str(e)}')

        # Continue to wait for and handle next module build which moves
        # to ready state.
        return

    logger.debug('Modulemd file is downloaded and parsed.')

    rule_matches = []
    for i, rule_def in enumerate(rule_defs, 1):
        rd = RuleDef(rule_def)
        logger.info('[%s] Checking rule definition: %s', i, rd.id)
        match = rd.match(modulemd)
        if match:
            rule_matches.append(match)
            logger.info('[%d] Rule definition: Matched.', i)
        else:
            logger.info('[%d] Rule definition: Not Matched.', i)

    if not rule_matches:
        logger.info('Module build %s does not match any rule.', nsvc)
        return

    stream = this_stream.replace('-', '_')
    nvr = f'{this_name}-{stream}-{this_version}.{this_context}'
    dest_tags = [item.dest_tag for item in rule_matches]
    logger.info('Tag build %s with tag(s) %s', nvr, ', '.join(dest_tags))

    tagged_tags = tag_build(nvr, dest_tags)

    if not tagged_tags:
        logger.warning(
            'None of tag(s) %r is tagged to build %s. Skip to send message.',
            dest_tags, nvr)
        return

    messaging.publish(
        'build.tagged', {
            'build': {
                'id': event_msg['id'],
                'name': this_name,
                'stream': this_stream,
                'version': this_version,
                'context': this_context,
            },
            'nvr': nvr,
            'destination_tags': tagged_tags,
        })
Esempio n. 3
0
    def test_send_via_rhmsg(self, AMQProducer, Message):
        msg = {'koji_tag': 'module-a-1-1-c1'}
        messaging.publish('build.tagged', msg)

        config = {
            'urls': ['amqps://broker1/', 'amqps://broker2/'],
            'certificate': '/path/to/certificate',
            'private_key': '/path/to/private_key',
            'trusted_certificates': '/path/to/ca_cert',
        }
        AMQProducer.assert_called_once_with(**config)
        producer = AMQProducer.return_value.__enter__.return_value
        producer.through_topic.assert_called_once_with('VirtualTopic.eng.mts.build.tagged')

        Message.return_value.body = json.dumps(msg)
        producer.send.assert_called_once_with(Message.return_value)
Esempio n. 4
0
def handle(rule_defs, event_msg):
    this_name = event_msg["name"]
    this_stream = event_msg["stream"]
    this_version = event_msg["version"]
    this_context = event_msg["context"]
    nsvc = f"{this_name}-{this_stream}-{this_version}-{this_context}"

    try:
        modulemd = yaml.safe_load(retrieve_modulemd_content(event_msg['id']))
    except requests.exceptions.HTTPError as e:
        logger.exception(f'Failed to retrieve modulemd for {nsvc}: {str(e)}')

        # Continue to wait for and handle next module build which moves
        # to ready state.
        return

    logger.debug('Modulemd file is downloaded and parsed.')

    rule_match = None
    for i, rule_def in enumerate(rule_defs, 1):
        rd = RuleDef(rule_def)
        logger.info('[%s] Checking rule definition: %s', i, rd.id)
        match = rd.match(modulemd)
        if match:
            logger.info(
                '[%d] Rule definition: Matched. Remaining rules ignored.', i)
            rule_match = match
            break
        else:
            logger.info('[%d] Rule definition: Not Matched.', i)

    if not rule_match:
        logger.info('Module build %s does not match any rule.', nsvc)
        messaging.publish(
            'build.tag.unmatched', {
                'build': {
                    'id': event_msg['id'],
                    'name': this_name,
                    'stream': this_stream,
                    'version': this_version,
                    'context': this_context,
                },
            })
        return

    monitor.matched_module_builds_counter.inc()

    stream = this_stream.replace('-', '_')
    with make_koji_session() as koji_session:
        for name in (this_name, f'{this_name}-devel'):
            nvr = f'{name}-{stream}-{this_version}.{this_context}'

            dest_tags = rule_match.dest_tags
            logger.info('Tag build %s with tag(s) %s', nvr,
                        ', '.join(dest_tags))
            tag_build_result = tag_build(nvr, dest_tags, koji_session)

            failed_tasks = [
                item for item in tag_build_result if item.task_id is None
            ]

            if len(failed_tasks) == len(dest_tags):
                logger.warning(
                    'None of tag(s) %r is applied to build %s successfully.',
                    dest_tags, nvr)
            elif len(failed_tasks) > 0:
                logger.warning(
                    'Tag(s) %r should be applied to build %s. But some of them,'
                    ' %s, failed to be applied.', nvr, dest_tags,
                    [item[0] for item in failed_tasks])

            # Tag info for message sent later
            # For a successful tag task, it is {"tag": "name", "task_id": 123}
            # For a failure tag task, it is {"tag": "name", "task_id": None, "reason": "..."}
            destination_tags = []
            for result in tag_build_result:
                data = {'tag': result.tag_name, 'task_id': result.task_id}
                if result.task_id is None:
                    data['error'] = result.error
                destination_tags.append(data)

            messaging.publish(
                'build.tag.requested', {
                    'build': {
                        'id': event_msg['id'],
                        'name': name,
                        'stream': this_stream,
                        'version': this_version,
                        'context': this_context,
                    },
                    'nvr': nvr,
                    'destination_tags': destination_tags,
                })
def handle(rule_defs, event_msg):
    """Handle MBS build.state.change event"""

    this_name = event_msg["name"]
    this_stream = event_msg["stream"]
    this_version = event_msg["version"]
    this_context = event_msg["context"]
    nsvc = f"{this_name}-{this_stream}-{this_version}-{this_context}"
    state_name = event_msg['state_name']

    # Rule definitions are grouped by build state:
    # ready: [{...}, {...}]
    # done: [{...}, {...}, {...}]
    rules_by_state = {}
    for i, rule_def in enumerate(rule_defs, 1):
        # Rule definitions are grouped by build state in rules_by_state, so
        # it is not necessary to keep build state in rule definition.
        build_state = rule_def.get('rule', {}).pop('build_state',
                                                   conf.build_state)
        # Keep the original index number so that it could be shown in logs
        rules_by_state.setdefault(build_state, []).append((i, rule_def))

    if state_name not in rules_by_state:
        logger.info(
            'Skip module build %s. It is in state "%s", no rule is '
            'defined for this state.', nsvc, state_name)
        return

    try:
        modulemd = yaml.safe_load(retrieve_modulemd_content(event_msg['id']))
    except requests.exceptions.HTTPError as e:
        raise RuntimeError(f'Failed to retrieve modulemd for {nsvc}: {str(e)}')

    logger.debug('Modulemd file is downloaded and parsed.')

    rule_match = None
    for i, rule_def in rules_by_state[state_name]:
        rd = RuleDef(rule_def)
        logger.info('[%s] Checking rule definition: %s', i, rd.id)
        match = rd.match(modulemd)
        if match:
            logger.info(
                '[%d] Rule definition: Matched. Remaining rules ignored.', i)
            rule_match = match
            break
        else:
            logger.info('[%d] Rule definition: Not Matched.', i)

    if not rule_match:
        logger.info('Module build %s does not match any rule.', nsvc)
        messaging.publish(
            'build.tag.unmatched', {
                'build': {
                    'id': event_msg['id'],
                    'name': this_name,
                    'stream': this_stream,
                    'version': this_version,
                    'context': this_context,
                },
            })
        return

    monitor.matched_module_builds_counter.inc()

    stream = this_stream.replace('-', '_')
    with make_koji_session() as koji_session:
        for name in (this_name, f'{this_name}-devel'):
            nvr = f'{name}-{stream}-{this_version}.{this_context}'

            dest_tags = rule_match.dest_tags
            logger.info('Tag build %s with tag(s) %s', nvr,
                        ', '.join(dest_tags))
            tag_build_result = tag_build(nvr, dest_tags, koji_session)

            failed_tasks = [
                item for item in tag_build_result if item.task_id is None
            ]

            if len(failed_tasks) == len(dest_tags):
                logger.warning(
                    'None of tag(s) %r is applied to build %s successfully.',
                    dest_tags, nvr)
                log_failed_tasks(failed_tasks)
            elif len(failed_tasks) > 0:
                logger.warning(
                    'Tag(s) %r should be applied to build %s. But failed to '
                    'apply these tags: %s', dest_tags, nvr,
                    [item.tag_name for item in failed_tasks])
                log_failed_tasks(failed_tasks)

            # Tag info for message sent later
            # For a successful tag task, it is {"tag": "name", "task_id": 123}
            # For a failure tag task, it is {"tag": "name", "task_id": None, "reason": "..."}
            destination_tags = []
            for result in tag_build_result:
                data = {'tag': result.tag_name, 'task_id': result.task_id}
                if result.task_id is None:
                    data['error'] = result.error
                destination_tags.append(data)

            messaging.publish(
                'build.tag.requested', {
                    'build': {
                        'id': event_msg['id'],
                        'name': name,
                        'stream': this_stream,
                        'version': this_version,
                        'context': this_context,
                    },
                    'nvr': nvr,
                    'destination_tags': destination_tags,
                })
Esempio n. 6
0
 def test_no_backend_handler_is_found(self):
     with pytest.raises(KeyError):
         messaging.publish('topic', {})
Esempio n. 7
0
    def test_send_via_fedmsg(self, publish):
        messaging.publish('build.tagged', {'build_id': 1})

        publish.assert_called_once_with(
            'build.tagged', msg={'build_id': 1}, modname='myapp')