Example #1
0
def test_add_default_modules_request_failed(mock_get_dm):
    """
    Test that an exception is raised when the call to _get_default_modules failed.
    """
    clean_database()
    make_module_in_db("python:3:12345:1")
    make_module_in_db("nodejs:11:2345:2")
    mmd = load_mmd(read_staged_data("formatted_testmodule.yaml"))
    xmd_brs = mmd.get_xmd()["mbs"]["buildrequires"]
    assert set(xmd_brs.keys()) == {"platform"}

    platform = ModuleBuild.get_build_from_nsvc(
        db_session,
        "platform",
        xmd_brs["platform"]["stream"],
        xmd_brs["platform"]["version"],
        xmd_brs["platform"]["context"],
    )
    assert platform
    platform_mmd = platform.mmd()
    platform_xmd = mmd.get_xmd()
    platform_xmd["mbs"]["use_default_modules"] = True
    platform_mmd.set_xmd(platform_xmd)
    platform.modulemd = mmd_to_str(platform_mmd)
    db_session.commit()

    expected_error = "some error"
    mock_get_dm.side_effect = ValueError(expected_error)

    with pytest.raises(ValueError, match=expected_error):
        default_modules.add_default_modules(mmd)
Example #2
0
def test_add_default_modules_not_linked(mock_get_dm):
    """
    Test that no default modules are added when they aren't linked from the base module.
    """
    clean_database()
    mmd = load_mmd(read_staged_data("formatted_testmodule.yaml"))
    assert set(mmd.get_xmd()["mbs"]["buildrequires"].keys()) == {"platform"}
    default_modules.add_default_modules(mmd)
    assert set(mmd.get_xmd()["mbs"]["buildrequires"].keys()) == {"platform"}
    mock_get_dm.assert_not_called()
def test_add_default_modules_platform_not_available(require_empty_database):
    """
    Test that an exception is raised when the platform module that is buildrequired is missing.

    This error should never occur in practice.
    """
    mmd = load_mmd(read_staged_data("formatted_testmodule.yaml"))

    expected_error = "Failed to retrieve the module platform:f28:3:00000000 from the database"
    with pytest.raises(RuntimeError, match=expected_error):
        default_modules.add_default_modules(mmd)
def test_add_default_modules(mock_get_dm, mock_hc,
                             require_platform_and_default_arch):
    """
    Test that default modules present in the database are added, and the others are ignored.
    """
    mmd = load_mmd(read_staged_data("formatted_testmodule.yaml"))
    xmd_brs = mmd.get_xmd()["mbs"]["buildrequires"]
    assert set(xmd_brs.keys()) == {"platform"}

    platform = ModuleBuild.get_build_from_nsvc(
        db_session,
        "platform",
        xmd_brs["platform"]["stream"],
        xmd_brs["platform"]["version"],
        xmd_brs["platform"]["context"],
    )
    assert platform
    platform_mmd = platform.mmd()
    platform_xmd = mmd.get_xmd()
    platform_xmd["mbs"]["use_default_modules"] = True
    platform_mmd.set_xmd(platform_xmd)
    platform.modulemd = mmd_to_str(platform_mmd)

    dependencies = [{
        "requires": {
            "platform": ["f28"]
        },
        "buildrequires": {
            "platform": ["f28"]
        }
    }]
    make_module_in_db("python:3:12345:1",
                      base_module=platform,
                      dependencies=dependencies)
    make_module_in_db("nodejs:11:2345:2",
                      base_module=platform,
                      dependencies=dependencies)
    db_session.commit()

    mock_get_dm.return_value = {
        "nodejs": "11",
        "python": "3",
        "ruby": "2.6",
    }
    defaults_added = default_modules.add_default_modules(mmd)
    # Make sure that the default modules were added. ruby:2.6 will be ignored since it's not in
    # the database
    assert set(mmd.get_xmd()["mbs"]["buildrequires"].keys()) == {
        "nodejs", "platform", "python"
    }
    mock_get_dm.assert_called_once_with(
        "f28",
        "https://pagure.io/releng/fedora-module-defaults.git",
    )
    assert "ursine_rpms" not in mmd.get_xmd()["mbs"]
    assert defaults_added is True
Example #5
0
def test_add_default_modules_compatible_platforms(mock_get_dm):
    """
    Test that default modules built against compatible base module streams are added.
    """
    clean_database(add_platform_module=False)

    # Create compatible base modules.
    mmd = load_mmd(read_staged_data("platform"))
    for stream in ["f27", "f28"]:
        mmd = mmd.copy("platform", stream)

        # Set the virtual stream to "fedora" to make these base modules compatible.
        xmd = mmd.get_xmd()
        xmd["mbs"]["virtual_streams"] = ["fedora"]
        xmd["mbs"]["use_default_modules"] = True
        mmd.set_xmd(xmd)
        import_mmd(db_session, mmd)

    mmd = load_mmd(read_staged_data("formatted_testmodule.yaml"))
    xmd_brs = mmd.get_xmd()["mbs"]["buildrequires"]
    assert set(xmd_brs.keys()) == {"platform"}

    platform_f27 = ModuleBuild.get_build_from_nsvc(
        db_session, "platform", "f27", "3", "00000000")
    assert platform_f27

    # Create python default module which requires platform:f27 and therefore cannot be used
    # as default module for platform:f28.
    dependencies = [
        {"requires": {"platform": ["f27"]},
         "buildrequires": {"platform": ["f27"]}}]
    make_module_in_db("python:3:12345:1", base_module=platform_f27, dependencies=dependencies)

    # Create nodejs default module which requries any platform stream and therefore can be used
    # as default module for platform:f28.
    dependencies[0]["requires"]["platform"] = []
    make_module_in_db("nodejs:11:2345:2", base_module=platform_f27, dependencies=dependencies)
    db_session.commit()

    mock_get_dm.return_value = {
        "nodejs": "11",
        "python": "3",
        "ruby": "2.6",
    }
    defaults_added = default_modules.add_default_modules(mmd)
    # Make sure that the default modules were added. ruby:2.6 will be ignored since it's not in
    # the database
    assert set(mmd.get_xmd()["mbs"]["buildrequires"].keys()) == {"nodejs", "platform"}
    mock_get_dm.assert_called_once_with(
        "f28",
        "https://pagure.io/releng/fedora-module-defaults.git",
    )
    assert defaults_added is True
Example #6
0
def init(msg_id, module_build_id, module_build_state):
    """Called whenever a module enters the 'init' state.

    :param str msg_id: the original id of the message being handled, which is
        received from message bus.
    :param int module_build_id: the module build id.
    :param int module_build_state: the module build state.
    """
    build = models.ModuleBuild.get_by_id(db_session, module_build_id)

    state_init = models.BUILD_STATES["init"]
    if module_build_state == state_init and build.state != state_init:
        log.warning("Module build %r has moved to %s state already.", build,
                    models.INVERSE_BUILD_STATES[build.state])
        log.warning(
            "Ignore this message %s. Is there something wrong with the frontend"
            " that sends duplicate messages?", msg_id)
        return

    # for MockModuleBuilder, set build logs dir to mock results dir
    # before build_logs start
    if conf.system == "mock":
        build_tag_name = generate_module_build_koji_tag(build)
        mock_resultsdir = os.path.join(conf.mock_resultsdir, build_tag_name)
        if not os.path.exists(mock_resultsdir):
            os.makedirs(mock_resultsdir)
        build_logs.build_logs_dir = mock_resultsdir

    build_logs.start(db_session, build)
    log.info("Start to handle %s which is in init state.",
             build.mmd().get_nsvc())

    error_msg = ""
    failure_reason = "unspec"
    try:
        mmd = build.mmd()
        record_module_build_arches(mmd, build)
        arches = [arch.name for arch in build.arches]
        defaults_added = add_default_modules(mmd)

        # Get map of packages that have SRPM overrides
        srpm_overrides = get_module_srpm_overrides(build)
        # Format the modulemd by putting in defaults and replacing streams that
        # are branches with commit hashes
        format_mmd(mmd, build.scmurl, build, db_session, srpm_overrides)
        record_component_builds(mmd, build)

        # The ursine.handle_stream_collision_modules is Koji specific.
        # It is also run only when Ursa Prime is not enabled for the base
        # module (`if not defaults_added`).
        if conf.system in ["koji", "test"] and not defaults_added:
            handle_stream_collision_modules(mmd)

        # Sets xmd["mbs"]["ursine_rpms"] with RPMs from the buildrequired base modules which
        # conflict with the RPMs from other buildrequired modules. This is done to prefer modular
        # RPMs over base module RPMs even if their NVR is lower.
        if conf.system in ("koji", "test"):
            handle_collisions_with_base_module_rpms(mmd, arches)
        else:
            log.warning(
                "The necessary conflicts could not be generated due to RHBZ#1693683. "
                "Some RPMs from the base modules (%s) may end up being used over modular RPMs. "
                "This may result in different behavior than a production build.",
                ", ".join(conf.base_module_names))

        mmd = record_filtered_rpms(mmd)
        build.modulemd = mmd_to_str(mmd)
        build.transition(db_session, conf, models.BUILD_STATES["wait"])
    # Catch custom exceptions that we can expose to the user
    except (UnprocessableEntity, Forbidden, ValidationError,
            RuntimeError) as e:
        log.exception(str(e))
        error_msg = str(e)
        failure_reason = "user"
    except (xmlrpclib.ProtocolError, koji.GenericError) as e:
        log.exception(str(e))
        error_msg = 'Koji communication error: "{0}"'.format(str(e))
        failure_reason = "infra"
    except Exception as e:
        log.exception(str(e))
        error_msg = "An unknown error occurred while validating the modulemd"
        failure_reason = "user"
    else:
        db_session.add(build)
        db_session.commit()
    finally:
        if error_msg:
            # Rollback changes underway
            db_session.rollback()
            build.transition(
                db_session,
                conf,
                models.BUILD_STATES["failed"],
                state_reason=error_msg,
                failure_type=failure_reason,
            )
            db_session.commit()