mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-02-03 05:03:43 +08:00
This will enable building modules from the new libmodulemd v3 format. This format fixes major issue with modularity which enables clear upgrade paths for multicontext modules. Signed-off-by: Martin Curlej <mcurlej@redhat.com>
290 lines
9.3 KiB
Python
290 lines
9.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# SPDX-License-Identifier: MIT
|
|
from __future__ import absolute_import
|
|
import mock
|
|
|
|
import pytest
|
|
|
|
from module_build_service.common import models
|
|
from module_build_service.common.errors import UnprocessableEntity
|
|
from module_build_service.common.utils import (import_mmd, load_mmd,
|
|
provide_module_stream_version_from_mmd,
|
|
provide_module_stream_version_from_timestamp)
|
|
from module_build_service.scheduler.db_session import db_session
|
|
from tests import read_staged_data, staged_data_filename
|
|
|
|
|
|
@pytest.mark.parametrize("context", ["c1", None])
|
|
def test_import_mmd_contexts(context):
|
|
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
|
mmd.set_context(context)
|
|
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"]["koji_tag"] = "foo"
|
|
mmd.set_xmd(xmd)
|
|
|
|
build, msgs = import_mmd(db_session, mmd)
|
|
|
|
mmd_context = build.mmd().get_context()
|
|
if context:
|
|
assert mmd_context == context
|
|
assert build.context == context
|
|
else:
|
|
assert mmd_context == models.DEFAULT_MODULE_CONTEXT
|
|
assert build.context == models.DEFAULT_MODULE_CONTEXT
|
|
|
|
|
|
def test_import_mmd_multiple_dependencies():
|
|
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
|
mmd.add_dependencies(mmd.get_dependencies()[0].copy())
|
|
|
|
expected_error = "The imported module's dependencies list should contain just one element"
|
|
with pytest.raises(UnprocessableEntity) as e:
|
|
import_mmd(db_session, mmd)
|
|
assert str(e.value) == expected_error
|
|
|
|
|
|
def test_import_mmd_no_xmd_buildrequires():
|
|
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
|
xmd = mmd.get_xmd()
|
|
del xmd["mbs"]["buildrequires"]
|
|
mmd.set_xmd(xmd)
|
|
|
|
expected_error = (
|
|
"The imported module buildrequires other modules, but the metadata in the "
|
|
'xmd["mbs"]["buildrequires"] dictionary is missing entries'
|
|
)
|
|
with pytest.raises(UnprocessableEntity) as e:
|
|
import_mmd(db_session, mmd)
|
|
assert str(e.value) == expected_error
|
|
|
|
|
|
def test_import_mmd_minimal_xmd_from_local_repository():
|
|
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"] = {}
|
|
xmd["mbs"]["koji_tag"] = "repofile:///etc/yum.repos.d/fedora-modular.repo"
|
|
xmd["mbs"]["mse"] = True
|
|
xmd["mbs"]["commit"] = "unknown"
|
|
mmd.set_xmd(xmd)
|
|
|
|
build, msgs = import_mmd(db_session, mmd, False)
|
|
assert build.name == mmd.get_module_name()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"stream, disttag_marking, error_msg",
|
|
(
|
|
("f28", None, None),
|
|
("f28", "fedora28", None),
|
|
("f-28", "f28", None),
|
|
("f-28", None, "The stream cannot contain a dash unless disttag_marking is set"),
|
|
("f28", "f-28", "The disttag_marking cannot contain a dash"),
|
|
("f-28", "fedora-28", "The disttag_marking cannot contain a dash"),
|
|
),
|
|
)
|
|
def test_import_mmd_base_module(stream, disttag_marking, error_msg, require_empty_database):
|
|
mmd = load_mmd(read_staged_data("platform"))
|
|
mmd = mmd.copy(mmd.get_module_name(), stream)
|
|
|
|
if disttag_marking:
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"]["disttag_marking"] = disttag_marking
|
|
mmd.set_xmd(xmd)
|
|
|
|
if error_msg:
|
|
with pytest.raises(UnprocessableEntity, match=error_msg):
|
|
import_mmd(db_session, mmd)
|
|
else:
|
|
import_mmd(db_session, mmd)
|
|
|
|
|
|
def test_import_mmd_remove_dropped_virtual_streams():
|
|
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
|
|
|
# Add some virtual streams
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"]["virtual_streams"] = ["f28", "f29", "f30"]
|
|
mmd.set_xmd(xmd)
|
|
|
|
# Import mmd into database to simulate the next step to reimport a module
|
|
import_mmd(db_session, mmd)
|
|
|
|
# Now, remove some virtual streams from module metadata
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"]["virtual_streams"] = ["f28", "f29"] # Note that, f30 is removed
|
|
mmd.set_xmd(xmd)
|
|
|
|
# Test import modulemd again and the f30 should be removed from database.
|
|
module_build, _ = import_mmd(db_session, mmd)
|
|
|
|
db_session.refresh(module_build)
|
|
assert ["f28", "f29"] == sorted(item.name for item in module_build.virtual_streams)
|
|
assert 0 == db_session.query(models.VirtualStream).filter_by(name="f30").count()
|
|
|
|
|
|
def test_import_mmd_dont_remove_dropped_virtual_streams_associated_with_other_modules():
|
|
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
|
# Add some virtual streams to this module metadata
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"]["virtual_streams"] = ["f28", "f29", "f30"]
|
|
mmd.set_xmd(xmd)
|
|
import_mmd(db_session, mmd)
|
|
|
|
# Import another module which has overlapping virtual streams
|
|
another_mmd = load_mmd(read_staged_data("formatted_testmodule-more-components"))
|
|
# Add some virtual streams to this module metadata
|
|
xmd = another_mmd.get_xmd()
|
|
xmd["mbs"]["virtual_streams"] = ["f29", "f30"]
|
|
another_mmd.set_xmd(xmd)
|
|
another_module_build, _ = import_mmd(
|
|
db_session, another_mmd)
|
|
|
|
# Now, remove f30 from mmd
|
|
xmd = mmd.get_xmd()
|
|
xmd["mbs"]["virtual_streams"] = ["f28", "f29"]
|
|
mmd.set_xmd(xmd)
|
|
|
|
# Reimport formatted_testmodule again
|
|
module_build, _ = import_mmd(db_session, mmd)
|
|
|
|
db_session.refresh(module_build)
|
|
assert ["f28", "f29"] == sorted(item.name for item in module_build.virtual_streams)
|
|
|
|
# The overlapped f30 should be still there.
|
|
db_session.refresh(another_module_build)
|
|
assert ["f29", "f30"] == sorted(item.name for item in another_module_build.virtual_streams)
|
|
|
|
|
|
def test_load_mmd_v2():
|
|
"""
|
|
Test to check if we can load a v2 packager file.
|
|
"""
|
|
mmd = load_mmd(read_staged_data("testmodule_v2.yaml"))
|
|
|
|
assert mmd.get_mdversion() == 2
|
|
|
|
dep = mmd.get_dependencies()
|
|
btm = dep[0].get_buildtime_modules()
|
|
rtm = dep[0].get_runtime_modules()
|
|
|
|
assert len(btm) == 1
|
|
assert len(rtm) == 1
|
|
assert btm[0] == "platform"
|
|
assert rtm[0] == "platform"
|
|
|
|
bts = dep[0].get_buildtime_streams(btm[0])
|
|
rts = dep[0].get_runtime_streams(rtm[0])
|
|
|
|
assert len(bts) == 1
|
|
assert len(rts) == 1
|
|
assert bts[0] == "f28"
|
|
assert rts[0] == "f28"
|
|
|
|
|
|
def test_load_mmd_v3():
|
|
"""
|
|
Test to check if we can load a v3 packager file.
|
|
"""
|
|
mmd = load_mmd(read_staged_data("v3/mmd_packager.yaml"))
|
|
|
|
assert mmd.get_mdversion() == 3
|
|
contexts = mmd.get_build_config_contexts_as_strv()
|
|
bc1 = mmd.get_build_config(contexts[0])
|
|
assert bc1.get_context() == "CTX1"
|
|
assert bc1.get_platform() == "f28"
|
|
btm1 = bc1.get_buildtime_modules_as_strv()
|
|
rtm1 = bc1.get_runtime_modules_as_strv()
|
|
assert len(btm1) == 0
|
|
assert len(rtm1) == 1
|
|
assert rtm1[0] == "nginx"
|
|
assert bc1.get_runtime_requirement_stream(rtm1[0]) == "1"
|
|
|
|
bc2 = mmd.get_build_config(contexts[1])
|
|
assert bc2.get_context() == "CTX2"
|
|
assert bc2.get_platform() == "f29"
|
|
assert not bc2.get_buildtime_modules_as_strv()
|
|
assert not bc2.get_runtime_modules_as_strv()
|
|
|
|
|
|
def test_provide_module_stream_version_from_timestamp():
|
|
ux_timestamp = "1613048427"
|
|
version = provide_module_stream_version_from_timestamp(ux_timestamp)
|
|
assert version == 20210211130027
|
|
|
|
|
|
@mock.patch("module_build_service.common.utils.time")
|
|
def test_provide_module_stream_version_from_timestamp_no_params(mock_time):
|
|
mock_time.time.return_value = "1613048427"
|
|
|
|
version = provide_module_stream_version_from_timestamp()
|
|
|
|
assert version == 20210211130027
|
|
|
|
|
|
def test_provide_module_stream_version_from_mmd_v2():
|
|
expected_version = 20210211130027
|
|
|
|
mmd = load_mmd(read_staged_data("testmodule_v2.yaml"))
|
|
mmd.set_version(expected_version)
|
|
|
|
version = provide_module_stream_version_from_mmd(mmd)
|
|
|
|
assert version == expected_version
|
|
|
|
|
|
@mock.patch("module_build_service.common.utils.time")
|
|
def test_provide_module_stream_version_from_mmd_v2_no_set_version(mock_time):
|
|
mock_time.time.return_value = "1613048427"
|
|
|
|
mmd = load_mmd(read_staged_data("testmodule_v2.yaml"))
|
|
|
|
version = provide_module_stream_version_from_mmd(mmd)
|
|
|
|
assert version == 20210211130027
|
|
|
|
|
|
@mock.patch("module_build_service.common.utils.time")
|
|
def test_provide_module_stream_version_from_mmd_v3(mock_time):
|
|
mock_time.time.return_value = "1613048427"
|
|
|
|
mmd = load_mmd(read_staged_data("v3/mmd_packager.yaml"))
|
|
|
|
version = provide_module_stream_version_from_mmd(mmd)
|
|
|
|
assert version == 20210211130027
|
|
|
|
|
|
def test_load_mmd_bad_mdversion_raise():
|
|
bad_mdversion_mmd = read_staged_data("v3/mmd_packager.yaml").replace("3", "4")
|
|
|
|
with pytest.raises(UnprocessableEntity) as e:
|
|
load_mmd(bad_mdversion_mmd)
|
|
|
|
err_msg = e.value.args[0]
|
|
assert "modulemd is invalid" in err_msg
|
|
assert "Invalid mdversion" in err_msg
|
|
assert "modulemd-yaml-error-quark" in err_msg
|
|
|
|
|
|
def test_load_mmd_missing_file_raise():
|
|
bad_path = "../something/something"
|
|
|
|
with pytest.raises(UnprocessableEntity) as e:
|
|
load_mmd(bad_path, is_file=True)
|
|
|
|
err_msg = e.value.args[0]
|
|
assert "file ../something/something was not found" in err_msg
|
|
|
|
|
|
def test_load_mmd_file_wrong_data_raise():
|
|
bad_file = staged_data_filename("bad.yaml")
|
|
|
|
with pytest.raises(UnprocessableEntity) as e:
|
|
load_mmd(bad_file, is_file=True)
|
|
|
|
err_msg = e.value.args[0]
|
|
assert "modulemd-yaml-error-quark" in err_msg
|
|
assert "Parse error identifying document type and version" in err_msg
|
|
assert "The modulemd bad.yaml is invalid" in err_msg
|