mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-04-13 11:49:52 +08:00
Split utils/general.py
This puts backend specific code in either the builder or scheduler subpackage. This puts API specific code in the new web subpackage. Lastly, any code shared between the API and backend is placed in the common subpackage.
This commit is contained in:
@@ -8,12 +8,13 @@ from six import string_types
|
||||
import time
|
||||
import hashlib
|
||||
from traceback import extract_stack
|
||||
from module_build_service.utils import to_text_type, load_mmd
|
||||
from module_build_service.common.utils import load_mmd, import_mmd
|
||||
|
||||
import koji
|
||||
import module_build_service
|
||||
from module_build_service import db
|
||||
from module_build_service.utils import get_rpm_release, import_mmd, mmd_to_str
|
||||
from module_build_service.builder.utils import get_rpm_release
|
||||
from module_build_service.common.utils import mmd_to_str, to_text_type
|
||||
from module_build_service.models import (
|
||||
ModuleBuild, ModuleArch, ComponentBuild, VirtualStream,
|
||||
BUILD_STATES,
|
||||
|
||||
@@ -7,10 +7,10 @@ import pytest
|
||||
from datetime import datetime
|
||||
|
||||
import module_build_service
|
||||
|
||||
from module_build_service.builder.utils import get_rpm_release
|
||||
from module_build_service.common.utils import load_mmd, mmd_to_str
|
||||
from module_build_service.models import BUILD_STATES
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.utils.general import mmd_to_str, load_mmd, get_rpm_release
|
||||
from tests import clean_database, read_staged_data, module_build_from_modulemd
|
||||
|
||||
BASE_DIR = os.path.dirname(__file__)
|
||||
|
||||
@@ -13,6 +13,8 @@ import hashlib
|
||||
import moksha.hub
|
||||
import fedmsg
|
||||
|
||||
from module_build_service.builder.utils import get_rpm_release
|
||||
from module_build_service.common.utils import load_mmd, import_mmd
|
||||
import module_build_service.messaging
|
||||
import module_build_service.scheduler.consumer
|
||||
import module_build_service.scheduler.handlers.repos
|
||||
@@ -35,6 +37,7 @@ import json
|
||||
import itertools
|
||||
|
||||
from module_build_service.builder import GenericBuilder
|
||||
from module_build_service.builder.utils import validate_koji_tag
|
||||
from module_build_service.builder.KojiModuleBuilder import KojiModuleBuilder
|
||||
from tests import clean_database, read_staged_data, staged_data_filename
|
||||
|
||||
@@ -180,7 +183,7 @@ class FakeModuleBuilder(GenericBuilder):
|
||||
on_buildroot_add_repos_cb = None
|
||||
on_get_task_info_cb = None
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_name")
|
||||
@validate_koji_tag("tag_name")
|
||||
def __init__(self, db_session, owner, module, config, tag_name, components):
|
||||
self.db_session = db_session
|
||||
self.module_str = module
|
||||
@@ -347,8 +350,7 @@ class FakeModuleBuilder(GenericBuilder):
|
||||
|
||||
def recover_orphaned_artifact(self, component_build):
|
||||
if self.INSTANT_COMPLETE:
|
||||
disttag = module_build_service.utils.get_rpm_release(
|
||||
self.db_session, component_build.module_build)
|
||||
disttag = get_rpm_release(self.db_session, component_build.module_build)
|
||||
# We don't know the version or release, so just use a random one here
|
||||
nvr = "{0}-1.0-1.{1}".format(component_build.package, disttag)
|
||||
component_build.state = koji.BUILD_STATES["COMPLETE"]
|
||||
@@ -1838,10 +1840,8 @@ class TestBuild(BaseTestBuild):
|
||||
Test that when a build is submitted with a buildrequire without a Koji tag,
|
||||
MBS doesn't supply it as a dependency to the builder.
|
||||
"""
|
||||
metadata_mmd = module_build_service.utils.load_mmd(
|
||||
read_staged_data("build_metadata_module")
|
||||
)
|
||||
module_build_service.utils.import_mmd(db_session, metadata_mmd)
|
||||
metadata_mmd = load_mmd(read_staged_data("build_metadata_module"))
|
||||
import_mmd(db_session, metadata_mmd)
|
||||
|
||||
FakeSCM(
|
||||
mocked_scm,
|
||||
|
||||
@@ -3,122 +3,351 @@
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from mock import patch, Mock, call
|
||||
from mock import call, MagicMock, Mock, patch, PropertyMock
|
||||
import pytest
|
||||
|
||||
from module_build_service import conf
|
||||
from module_build_service import conf, models
|
||||
from module_build_service.builder import utils
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.errors import ProgrammingError, ValidationError
|
||||
from module_build_service.common.utils import load_mmd, import_mmd, mmd_to_str
|
||||
from tests import init_data, read_staged_data, scheduler_init_data
|
||||
|
||||
|
||||
class TestBuilderUtils:
|
||||
@patch("requests.get")
|
||||
@patch("koji.ClientSession")
|
||||
@patch("module_build_service.builder.utils.execute_cmd")
|
||||
def test_create_local_repo_from_koji_tag(self, mock_exec_cmd, mock_koji_session, mock_get):
|
||||
session = Mock()
|
||||
rpms = [
|
||||
{
|
||||
"arch": "src",
|
||||
"build_id": 875991,
|
||||
"name": "module-build-macros",
|
||||
"release": "1.module_92011fe6",
|
||||
"size": 6890,
|
||||
"version": "0.1",
|
||||
},
|
||||
{
|
||||
"arch": "noarch",
|
||||
"build_id": 875991,
|
||||
"name": "module-build-macros",
|
||||
"release": "1.module_92011fe6",
|
||||
"size": 6890,
|
||||
"version": "0.1",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875636,
|
||||
"name": "ed-debuginfo",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 81438,
|
||||
"version": "1.14.1",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875636,
|
||||
"name": "ed",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 80438,
|
||||
"version": "1.14.1",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875640,
|
||||
"name": "mksh-debuginfo",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 578774,
|
||||
"version": "54",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875640,
|
||||
"name": "mksh",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 267042,
|
||||
"version": "54",
|
||||
},
|
||||
]
|
||||
@patch("requests.get")
|
||||
@patch("koji.ClientSession")
|
||||
@patch("module_build_service.builder.utils.execute_cmd")
|
||||
def test_create_local_repo_from_koji_tag(mock_exec_cmd, mock_koji_session, mock_get):
|
||||
session = Mock()
|
||||
rpms = [
|
||||
{
|
||||
"arch": "src",
|
||||
"build_id": 875991,
|
||||
"name": "module-build-macros",
|
||||
"release": "1.module_92011fe6",
|
||||
"size": 6890,
|
||||
"version": "0.1",
|
||||
},
|
||||
{
|
||||
"arch": "noarch",
|
||||
"build_id": 875991,
|
||||
"name": "module-build-macros",
|
||||
"release": "1.module_92011fe6",
|
||||
"size": 6890,
|
||||
"version": "0.1",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875636,
|
||||
"name": "ed-debuginfo",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 81438,
|
||||
"version": "1.14.1",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875636,
|
||||
"name": "ed",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 80438,
|
||||
"version": "1.14.1",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875640,
|
||||
"name": "mksh-debuginfo",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 578774,
|
||||
"version": "54",
|
||||
},
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"build_id": 875640,
|
||||
"name": "mksh",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"size": 267042,
|
||||
"version": "54",
|
||||
},
|
||||
]
|
||||
|
||||
builds = [
|
||||
{
|
||||
"build_id": 875640,
|
||||
"name": "mksh",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"version": "54",
|
||||
"volume_name": "prod",
|
||||
},
|
||||
{
|
||||
"build_id": 875636,
|
||||
"name": "ed",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"version": "1.14.1",
|
||||
"volume_name": "prod",
|
||||
},
|
||||
{
|
||||
"build_id": 875991,
|
||||
"name": "module-build-macros",
|
||||
"release": "1.module_92011fe6",
|
||||
"version": "0.1",
|
||||
"volume_name": "prod",
|
||||
},
|
||||
]
|
||||
builds = [
|
||||
{
|
||||
"build_id": 875640,
|
||||
"name": "mksh",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"version": "54",
|
||||
"volume_name": "prod",
|
||||
},
|
||||
{
|
||||
"build_id": 875636,
|
||||
"name": "ed",
|
||||
"release": "2.module_bd6e0eb1",
|
||||
"version": "1.14.1",
|
||||
"volume_name": "prod",
|
||||
},
|
||||
{
|
||||
"build_id": 875991,
|
||||
"name": "module-build-macros",
|
||||
"release": "1.module_92011fe6",
|
||||
"version": "0.1",
|
||||
"volume_name": "prod",
|
||||
},
|
||||
]
|
||||
|
||||
session.listTaggedRPMS.return_value = (rpms, builds)
|
||||
session.opts = {"topurl": "https://kojipkgs.stg.fedoraproject.org/"}
|
||||
mock_koji_session.return_value = session
|
||||
session.listTaggedRPMS.return_value = (rpms, builds)
|
||||
session.opts = {"topurl": "https://kojipkgs.stg.fedoraproject.org/"}
|
||||
mock_koji_session.return_value = session
|
||||
|
||||
tag = "module-testmodule-master-20170405123740-build"
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
utils.create_local_repo_from_koji_tag(conf, tag, temp_dir)
|
||||
finally:
|
||||
shutil.rmtree(temp_dir)
|
||||
tag = "module-testmodule-master-20170405123740-build"
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
try:
|
||||
utils.create_local_repo_from_koji_tag(conf, tag, temp_dir)
|
||||
finally:
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
url_one = (
|
||||
"https://kojipkgs.stg.fedoraproject.org//vol/prod/packages/module-build-macros/"
|
||||
"0.1/1.module_92011fe6/noarch/module-build-macros-0.1-1.module_92011fe6.noarch.rpm"
|
||||
)
|
||||
url_two = (
|
||||
"https://kojipkgs.stg.fedoraproject.org//vol/prod/packages/ed/1.14.1/"
|
||||
"2.module_bd6e0eb1/x86_64/ed-1.14.1-2.module_bd6e0eb1.x86_64.rpm"
|
||||
)
|
||||
url_three = (
|
||||
"https://kojipkgs.stg.fedoraproject.org//vol/prod/packages/mksh/54/"
|
||||
"2.module_bd6e0eb1/x86_64/mksh-54-2.module_bd6e0eb1.x86_64.rpm"
|
||||
)
|
||||
url_one = (
|
||||
"https://kojipkgs.stg.fedoraproject.org//vol/prod/packages/module-build-macros/"
|
||||
"0.1/1.module_92011fe6/noarch/module-build-macros-0.1-1.module_92011fe6.noarch.rpm"
|
||||
)
|
||||
url_two = (
|
||||
"https://kojipkgs.stg.fedoraproject.org//vol/prod/packages/ed/1.14.1/"
|
||||
"2.module_bd6e0eb1/x86_64/ed-1.14.1-2.module_bd6e0eb1.x86_64.rpm"
|
||||
)
|
||||
url_three = (
|
||||
"https://kojipkgs.stg.fedoraproject.org//vol/prod/packages/mksh/54/"
|
||||
"2.module_bd6e0eb1/x86_64/mksh-54-2.module_bd6e0eb1.x86_64.rpm"
|
||||
)
|
||||
|
||||
expected_calls = [
|
||||
call(url_one, stream=True, timeout=60),
|
||||
call(url_two, stream=True, timeout=60),
|
||||
call(url_three, stream=True, timeout=60),
|
||||
]
|
||||
for expected_call in expected_calls:
|
||||
assert expected_call in mock_get.call_args_list
|
||||
assert len(mock_get.call_args_list) == len(expected_calls)
|
||||
expected_calls = [
|
||||
call(url_one, stream=True, timeout=60),
|
||||
call(url_two, stream=True, timeout=60),
|
||||
call(url_three, stream=True, timeout=60),
|
||||
]
|
||||
for expected_call in expected_calls:
|
||||
assert expected_call in mock_get.call_args_list
|
||||
assert len(mock_get.call_args_list) == len(expected_calls)
|
||||
|
||||
|
||||
def test_validate_koji_tag_wrong_tag_arg_during_programming():
|
||||
""" Test that we fail on a wrong param name (non-existing one) due to
|
||||
programming error. """
|
||||
|
||||
@utils.validate_koji_tag("wrong_tag_arg")
|
||||
def validate_koji_tag_programming_error(good_tag_arg, other_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ProgrammingError):
|
||||
validate_koji_tag_programming_error("dummy", "other_val")
|
||||
|
||||
|
||||
def test_validate_koji_tag_bad_tag_value():
|
||||
""" Test that we fail on a bad tag value. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_bad_tag_value(tag_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validate_koji_tag_bad_tag_value("forbiddentagprefix-foo")
|
||||
|
||||
|
||||
def test_validate_koji_tag_bad_tag_value_in_list():
|
||||
""" Test that we fail on a list containing bad tag value. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_bad_tag_value_in_list(tag_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validate_koji_tag_bad_tag_value_in_list(["module-foo", "forbiddentagprefix-bar"])
|
||||
|
||||
|
||||
def test_validate_koji_tag_good_tag_value():
|
||||
""" Test that we pass on a good tag value. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_good_tag_value(tag_arg):
|
||||
return True
|
||||
|
||||
assert validate_koji_tag_good_tag_value("module-foo") is True
|
||||
|
||||
|
||||
def test_validate_koji_tag_good_tag_values_in_list():
|
||||
""" Test that we pass on a list of good tag values. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_good_tag_values_in_list(tag_arg):
|
||||
return True
|
||||
|
||||
assert validate_koji_tag_good_tag_values_in_list(["module-foo", "module-bar"]) is True
|
||||
|
||||
|
||||
def test_validate_koji_tag_good_tag_value_in_dict():
|
||||
""" Test that we pass on a dict arg with default key
|
||||
and a good value. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_good_tag_value_in_dict(tag_arg):
|
||||
return True
|
||||
|
||||
assert validate_koji_tag_good_tag_value_in_dict({"name": "module-foo"}) is True
|
||||
|
||||
|
||||
def test_validate_koji_tag_good_tag_value_in_dict_nondefault_key():
|
||||
""" Test that we pass on a dict arg with non-default key
|
||||
and a good value. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg", dict_key="nondefault")
|
||||
def validate_koji_tag_good_tag_value_in_dict_nondefault_key(tag_arg):
|
||||
return True
|
||||
|
||||
assert (
|
||||
validate_koji_tag_good_tag_value_in_dict_nondefault_key({"nondefault": "module-foo"})
|
||||
is True
|
||||
)
|
||||
|
||||
|
||||
def test_validate_koji_tag_double_trouble_good():
|
||||
""" Test that we pass on a list of tags that are good. """
|
||||
|
||||
expected = "foo"
|
||||
|
||||
@utils.validate_koji_tag(["tag_arg1", "tag_arg2"])
|
||||
def validate_koji_tag_double_trouble(tag_arg1, tag_arg2):
|
||||
return expected
|
||||
|
||||
actual = validate_koji_tag_double_trouble("module-1", "module-2")
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_validate_koji_tag_double_trouble_bad():
|
||||
""" Test that we fail on a list of tags that are bad. """
|
||||
|
||||
@utils.validate_koji_tag(["tag_arg1", "tag_arg2"])
|
||||
def validate_koji_tag_double_trouble(tag_arg1, tag_arg2):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validate_koji_tag_double_trouble("module-1", "BADNEWS-2")
|
||||
|
||||
|
||||
def test_validate_koji_tag_is_None():
|
||||
""" Test that we fail on a tag which is None. """
|
||||
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_is_None(tag_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError) as cm:
|
||||
validate_koji_tag_is_None(None)
|
||||
assert str(cm.value).endswith(" No value provided.") is True
|
||||
|
||||
|
||||
@patch(
|
||||
"module_build_service.config.Config.allowed_privileged_module_names",
|
||||
new_callable=PropertyMock,
|
||||
return_value=["testmodule"],
|
||||
)
|
||||
def test_validate_koji_tag_previleged_module_name(conf_apmn):
|
||||
@utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_priv_mod_name(self, tag_arg):
|
||||
pass
|
||||
|
||||
builder = MagicMock()
|
||||
builder.module_str = 'testmodule'
|
||||
validate_koji_tag_priv_mod_name(builder, "abc")
|
||||
|
||||
|
||||
def test_get_rpm_release_mse():
|
||||
init_data(contexts=True)
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release_one = utils.get_rpm_release(db_session, build_one)
|
||||
assert release_one == "module+2+b8645bbb"
|
||||
|
||||
build_two = models.ModuleBuild.get_by_id(db_session, 3)
|
||||
release_two = utils.get_rpm_release(db_session, build_two)
|
||||
assert release_two == "module+2+17e35784"
|
||||
|
||||
|
||||
def test_get_rpm_release_platform_stream():
|
||||
scheduler_init_data(1)
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release = utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "module+f28+2+814cfa39"
|
||||
|
||||
|
||||
def test_get_rpm_release_platform_stream_override():
|
||||
scheduler_init_data(1)
|
||||
|
||||
# Set the disttag_marking override on the platform
|
||||
platform = (
|
||||
db_session.query(models.ModuleBuild)
|
||||
.filter_by(name="platform", stream="f28")
|
||||
.first()
|
||||
)
|
||||
platform_mmd = platform.mmd()
|
||||
platform_xmd = platform_mmd.get_xmd()
|
||||
platform_xmd["mbs"]["disttag_marking"] = "fedora28"
|
||||
platform_mmd.set_xmd(platform_xmd)
|
||||
platform.modulemd = mmd_to_str(platform_mmd)
|
||||
db_session.add(platform)
|
||||
db_session.commit()
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release = utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "module+fedora28+2+814cfa39"
|
||||
|
||||
|
||||
@patch(
|
||||
"module_build_service.config.Config.allowed_privileged_module_names",
|
||||
new_callable=PropertyMock,
|
||||
return_value=["build"],
|
||||
)
|
||||
def test_get_rpm_release_metadata_br_stream_override(mock_admmn):
|
||||
"""
|
||||
Test that when a module buildrequires a module in conf.allowed_privileged_module_names,
|
||||
and that module has the xmd.mbs.disttag_marking field set, it should influence the disttag.
|
||||
"""
|
||||
scheduler_init_data(1)
|
||||
metadata_mmd = load_mmd(read_staged_data("build_metadata_module"))
|
||||
import_mmd(db_session, metadata_mmd)
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
mmd = build_one.mmd()
|
||||
deps = mmd.get_dependencies()[0]
|
||||
deps.add_buildtime_stream("build", "product1.2")
|
||||
xmd = mmd.get_xmd()
|
||||
xmd["mbs"]["buildrequires"]["build"] = {
|
||||
"filtered_rpms": [],
|
||||
"ref": "virtual",
|
||||
"stream": "product1.2",
|
||||
"version": "1",
|
||||
"context": "00000000",
|
||||
}
|
||||
mmd.set_xmd(xmd)
|
||||
build_one.modulemd = mmd_to_str(mmd)
|
||||
db_session.add(build_one)
|
||||
db_session.commit()
|
||||
|
||||
release = utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "module+product12+2+814cfa39"
|
||||
|
||||
|
||||
def test_get_rpm_release_mse_scratch():
|
||||
init_data(contexts=True, scratch=True)
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release_one = utils.get_rpm_release(db_session, build_one)
|
||||
assert release_one == "scrmod+2+b8645bbb"
|
||||
|
||||
build_two = models.ModuleBuild.get_by_id(db_session, 3)
|
||||
release_two = utils.get_rpm_release(db_session, build_two)
|
||||
assert release_two == "scrmod+2+17e35784"
|
||||
|
||||
|
||||
def test_get_rpm_release_platform_stream_scratch():
|
||||
scheduler_init_data(1, scratch=True)
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release = utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "scrmod+f28+2+814cfa39"
|
||||
|
||||
@@ -14,11 +14,11 @@ import module_build_service.messaging
|
||||
import module_build_service.scheduler.handlers.repos
|
||||
import module_build_service.models
|
||||
from module_build_service import conf, Modulemd
|
||||
from module_build_service.common.utils import mmd_to_str
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.builder.KojiModuleBuilder import KojiModuleBuilder
|
||||
from module_build_service.builder import GenericBuilder
|
||||
from module_build_service.scheduler import events
|
||||
from module_build_service.utils.general import mmd_to_str
|
||||
from tests import init_data, clean_database, make_module_in_db
|
||||
|
||||
|
||||
@@ -1030,3 +1030,21 @@ class TestGetDistTagSRPM:
|
||||
# Conflicting ursine RPMs
|
||||
for nevr in ["pizza-0:4.0-1.fc32", "spaghetti-0:3.0-1.fc32"]:
|
||||
assert KojiModuleBuilder.format_conflicts_line(nevr) + "\n" in content
|
||||
|
||||
|
||||
def test_generate_koji_tag_in_nsvc_format():
|
||||
name, stream, version, context = ("testmodule", "master", "20170816080815", "37c6c57")
|
||||
|
||||
tag = KojiModuleBuilder.generate_koji_tag(name, stream, version, context)
|
||||
|
||||
assert tag == "module-testmodule-master-20170816080815-37c6c57"
|
||||
|
||||
|
||||
def test_generate_koji_tag_in_hash_format():
|
||||
name, version, context = ("testmodule", "20170816080815", "37c6c57")
|
||||
stream = "this-is-a-stream-with-very-looooong-name" + "-blah" * 50
|
||||
nsvc_list = [name, stream, version, context]
|
||||
|
||||
tag = KojiModuleBuilder.generate_koji_tag(*nsvc_list)
|
||||
expected_tag = "module-1cf457d452e54dda"
|
||||
assert tag == expected_tag
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: MIT
|
||||
import os
|
||||
import mock
|
||||
import koji
|
||||
import tempfile
|
||||
import shutil
|
||||
from textwrap import dedent
|
||||
|
||||
import mock
|
||||
import kobo.rpmlib
|
||||
import koji
|
||||
|
||||
from module_build_service import conf
|
||||
from module_build_service import conf, models
|
||||
from module_build_service.common.utils import load_mmd, mmd_to_str
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.models import ModuleBuild, ComponentBuild
|
||||
from module_build_service.builder.MockModuleBuilder import MockModuleBuilder
|
||||
from module_build_service.utils import import_fake_base_module, mmd_to_str, load_mmd
|
||||
from module_build_service.builder.MockModuleBuilder import (
|
||||
import_fake_base_module, import_builds_from_local_dnf_repos, MockModuleBuilder,
|
||||
)
|
||||
from tests import clean_database, make_module_in_db, read_staged_data
|
||||
|
||||
|
||||
@@ -232,3 +234,69 @@ class TestMockModuleBuilderAddRepos:
|
||||
assert "repofile 3" in builder.yum_conf
|
||||
|
||||
assert set(builder.enabled_modules) == {"foo:1", "app:1"}
|
||||
|
||||
|
||||
class TestOfflineLocalBuilds:
|
||||
def setup_method(self):
|
||||
clean_database()
|
||||
|
||||
def teardown_method(self):
|
||||
clean_database()
|
||||
|
||||
def test_import_fake_base_module(self):
|
||||
import_fake_base_module("platform:foo:1:000000")
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "platform", "foo", 1, "000000")
|
||||
assert module_build
|
||||
|
||||
mmd = module_build.mmd()
|
||||
xmd = mmd.get_xmd()
|
||||
assert xmd == {
|
||||
"mbs": {
|
||||
"buildrequires": {},
|
||||
"commit": "ref_000000",
|
||||
"koji_tag": "repofile://",
|
||||
"mse": "true",
|
||||
"requires": {},
|
||||
}
|
||||
}
|
||||
|
||||
assert set(mmd.get_profile_names()) == {"buildroot", "srpm-buildroot"}
|
||||
|
||||
@mock.patch(
|
||||
"module_build_service.builder.MockModuleBuilder.open",
|
||||
create=True,
|
||||
new_callable=mock.mock_open,
|
||||
)
|
||||
def test_import_builds_from_local_dnf_repos(self, patched_open):
|
||||
with mock.patch("dnf.Base") as dnf_base:
|
||||
repo = mock.MagicMock()
|
||||
repo.repofile = "/etc/yum.repos.d/foo.repo"
|
||||
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
||||
repo.get_metadata_content.return_value = mmd_to_str(mmd)
|
||||
base = dnf_base.return_value
|
||||
base.repos = {"reponame": repo}
|
||||
patched_open.return_value.readlines.return_value = ("FOO=bar", "PLATFORM_ID=platform:x")
|
||||
|
||||
import_builds_from_local_dnf_repos()
|
||||
|
||||
base.read_all_repos.assert_called_once()
|
||||
repo.load.assert_called_once()
|
||||
repo.get_metadata_content.assert_called_once_with("modules")
|
||||
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "testmodule", "master", 20180205135154, "9c690d0e")
|
||||
assert module_build
|
||||
assert module_build.koji_tag == "repofile:///etc/yum.repos.d/foo.repo"
|
||||
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "platform", "x", 1, "000000")
|
||||
assert module_build
|
||||
|
||||
def test_import_builds_from_local_dnf_repos_platform_id(self):
|
||||
with mock.patch("dnf.Base"):
|
||||
import_builds_from_local_dnf_repos("platform:y")
|
||||
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "platform", "y", 1, "000000")
|
||||
assert module_build
|
||||
|
||||
152
tests/test_common/test_utils.py
Normal file
152
tests/test_common/test_utils.py
Normal file
@@ -0,0 +1,152 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# SPDX-License-Identifier: MIT
|
||||
import pytest
|
||||
|
||||
from module_build_service import models
|
||||
from module_build_service.common.utils import import_mmd, load_mmd
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.errors import UnprocessableEntity
|
||||
from tests import clean_database, read_staged_data
|
||||
|
||||
|
||||
@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):
|
||||
clean_database(add_platform_module=False)
|
||||
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)
|
||||
@@ -7,10 +7,9 @@ import json
|
||||
import os
|
||||
from os import path
|
||||
|
||||
import module_build_service.messaging
|
||||
from module_build_service import models, conf, build_logs, Modulemd
|
||||
from module_build_service.common.utils import load_mmd, load_mmd_file, mmd_to_str
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.utils.general import mmd_to_str
|
||||
|
||||
from mock import patch, Mock, call, mock_open
|
||||
import kobo.rpmlib
|
||||
@@ -128,10 +127,10 @@ class TestBuild:
|
||||
# For devel, only check that the name has -devel suffix.
|
||||
assert ret["build"]["name"] == "nginx-devel"
|
||||
assert ret["build"]["extra"]["typeinfo"]["module"]["name"] == "nginx-devel"
|
||||
new_mmd = module_build_service.utils.load_mmd(
|
||||
new_mmd = load_mmd(
|
||||
ret["build"]["extra"]["typeinfo"]["module"]["modulemd_str"])
|
||||
assert new_mmd.get_module_name().endswith("-devel")
|
||||
new_mmd = module_build_service.utils.load_mmd_file("%s/modulemd.txt" % file_dir)
|
||||
new_mmd = load_mmd_file("%s/modulemd.txt" % file_dir)
|
||||
assert new_mmd.get_module_name().endswith("-devel")
|
||||
|
||||
# Ensure an anonymous Koji session works
|
||||
@@ -951,7 +950,7 @@ class TestBuild:
|
||||
def test_finalize_mmd_devel(self):
|
||||
self.cg.devel = True
|
||||
mmd = self.cg.module.mmd()
|
||||
new_mmd = module_build_service.utils.load_mmd(self.cg._finalize_mmd("x86_64"))
|
||||
new_mmd = load_mmd(self.cg._finalize_mmd("x86_64"))
|
||||
|
||||
# Check that -devel suffix is set.
|
||||
assert new_mmd.get_module_name().endswith("-devel")
|
||||
|
||||
@@ -7,7 +7,7 @@ from module_build_service import app, models
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.manage import manager_wrapper, retire
|
||||
from module_build_service.models import BUILD_STATES, ModuleBuild
|
||||
from module_build_service.utils.general import deps_to_dict
|
||||
from module_build_service.web.utils import deps_to_dict
|
||||
from tests import clean_database, staged_data_filename
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import pytest
|
||||
|
||||
from mock import patch
|
||||
from module_build_service import conf
|
||||
from module_build_service.common.utils import load_mmd, mmd_to_str
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.models import ComponentBuild, ComponentBuildTrace, ModuleBuild
|
||||
from module_build_service.utils.general import mmd_to_str, load_mmd
|
||||
from tests import init_data as init_data_contexts, clean_database, read_staged_data
|
||||
from tests import make_module_in_db, module_build_from_modulemd
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import pytest
|
||||
|
||||
import module_build_service.resolver as mbs_resolver
|
||||
from module_build_service import conf, models, utils, Modulemd
|
||||
from module_build_service.utils import import_mmd, mmd_to_str, load_mmd
|
||||
from module_build_service.common.utils import import_mmd, load_mmd, mmd_to_str
|
||||
from module_build_service.models import ModuleBuild
|
||||
from module_build_service.errors import UnprocessableEntity
|
||||
from module_build_service.db_session import db_session
|
||||
|
||||
@@ -5,11 +5,11 @@ from mock import patch, MagicMock
|
||||
from datetime import datetime
|
||||
|
||||
from module_build_service import conf
|
||||
from module_build_service.common.utils import import_mmd, load_mmd, mmd_to_str
|
||||
import module_build_service.resolver as mbs_resolver
|
||||
import tests
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.models import ModuleBuild, BUILD_STATES
|
||||
from module_build_service.utils.general import import_mmd, mmd_to_str, load_mmd
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("reuse_component_init_data")
|
||||
|
||||
@@ -4,10 +4,10 @@ import pytest
|
||||
from datetime import datetime
|
||||
|
||||
from module_build_service import conf
|
||||
from module_build_service.common.utils import import_mmd, load_mmd, mmd_to_str
|
||||
import module_build_service.resolver as mbs_resolver
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.models import ModuleBuild
|
||||
from module_build_service.utils.general import import_mmd, mmd_to_str, load_mmd
|
||||
import tests
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
from mock import patch, PropertyMock, Mock, call
|
||||
|
||||
from module_build_service import app, conf
|
||||
from module_build_service.common.utils import load_mmd, mmd_to_str
|
||||
import module_build_service.resolver as mbs_resolver
|
||||
import module_build_service.utils
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.utils.general import mmd_to_str
|
||||
import module_build_service.models
|
||||
import tests
|
||||
|
||||
@@ -188,7 +188,7 @@ class TestMBSModule:
|
||||
self, mock_session, testmodule_mmd_9c690d0e
|
||||
):
|
||||
|
||||
mmd = module_build_service.utils.load_mmd(testmodule_mmd_9c690d0e)
|
||||
mmd = load_mmd(testmodule_mmd_9c690d0e)
|
||||
# Wipe out the dependencies
|
||||
for deps in mmd.get_dependencies():
|
||||
mmd.remove_dependencies(deps)
|
||||
|
||||
@@ -10,7 +10,7 @@ from module_build_service.builder import GenericBuilder
|
||||
from module_build_service.builder.KojiModuleBuilder import KojiModuleBuilder
|
||||
from module_build_service.scheduler import events
|
||||
from module_build_service.scheduler.batches import start_build_component, start_next_batch_build
|
||||
from module_build_service.utils import validate_koji_tag
|
||||
from module_build_service.builder.utils import validate_koji_tag
|
||||
|
||||
|
||||
class DummyModuleBuilder(GenericBuilder):
|
||||
|
||||
@@ -8,12 +8,12 @@ from mock import call, Mock, patch, PropertyMock
|
||||
import pytest
|
||||
|
||||
from module_build_service import conf
|
||||
from module_build_service.common.utils import import_mmd, load_mmd, mmd_to_str
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.errors import UnprocessableEntity
|
||||
from module_build_service.models import ModuleBuild
|
||||
from module_build_service.scheduler import default_modules
|
||||
from module_build_service.utils.general import load_mmd, mmd_to_str
|
||||
from tests import clean_database, make_module_in_db, read_staged_data, import_mmd
|
||||
from tests import clean_database, make_module_in_db, read_staged_data
|
||||
|
||||
|
||||
@patch("module_build_service.scheduler.default_modules.handle_collisions_with_base_module_rpms")
|
||||
|
||||
@@ -4,6 +4,7 @@ import os
|
||||
|
||||
from mock import patch, PropertyMock
|
||||
|
||||
from module_build_service.common.utils import load_mmd, mmd_to_str
|
||||
from tests import clean_database, read_staged_data
|
||||
from tests.test_views.test_views import FakeSCM
|
||||
import module_build_service.messaging
|
||||
@@ -11,8 +12,6 @@ import module_build_service.scheduler.handlers.modules
|
||||
from module_build_service import build_logs, conf
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.models import ModuleBuild
|
||||
from module_build_service.utils.general import mmd_to_str, load_mmd
|
||||
# from module_build_service.scheduler.events import MBSModule
|
||||
|
||||
|
||||
class TestModuleInit:
|
||||
|
||||
@@ -9,13 +9,13 @@ from datetime import datetime
|
||||
from werkzeug.datastructures import FileStorage
|
||||
from mock import patch
|
||||
from sqlalchemy.orm.session import make_transient
|
||||
from module_build_service.utils.general import load_mmd_file, mmd_to_str
|
||||
|
||||
from module_build_service.common.utils import import_mmd, load_mmd, load_mmd_file, mmd_to_str
|
||||
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, UnprocessableEntity
|
||||
from module_build_service.errors import ValidationError, UnprocessableEntity
|
||||
from module_build_service.utils.reuse import get_reusable_module, get_reusable_component
|
||||
from module_build_service.utils.general import load_mmd
|
||||
from module_build_service.utils.submit import format_mmd
|
||||
from tests import (
|
||||
clean_database,
|
||||
@@ -386,231 +386,6 @@ class TestUtils:
|
||||
r = module_build_service.utils.get_build_arches(mmd, conf)
|
||||
assert r == ["x86_64", "i686"]
|
||||
|
||||
@pytest.mark.parametrize("context", ["c1", None])
|
||||
def test_import_mmd_contexts(self, 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 = module_build_service.utils.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(self):
|
||||
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:
|
||||
module_build_service.utils.import_mmd(db_session, mmd)
|
||||
assert str(e.value) == expected_error
|
||||
|
||||
def test_import_mmd_no_xmd_buildrequires(self):
|
||||
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:
|
||||
module_build_service.utils.import_mmd(db_session, mmd)
|
||||
assert str(e.value) == expected_error
|
||||
|
||||
def test_import_mmd_minimal_xmd_from_local_repository(self):
|
||||
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 = module_build_service.utils.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(self, stream, disttag_marking, error_msg):
|
||||
clean_database(add_platform_module=False)
|
||||
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):
|
||||
module_build_service.utils.import_mmd(db_session, mmd)
|
||||
else:
|
||||
module_build_service.utils.import_mmd(db_session, mmd)
|
||||
|
||||
def test_import_mmd_remove_dropped_virtual_streams(self):
|
||||
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
|
||||
module_build_service.utils.general.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, _ = module_build_service.utils.general.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(self):
|
||||
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)
|
||||
module_build_service.utils.general.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, _ = module_build_service.utils.general.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, _ = module_build_service.utils.general.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_get_rpm_release_mse(self):
|
||||
init_data(contexts=True)
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release_one = module_build_service.utils.get_rpm_release(db_session, build_one)
|
||||
assert release_one == "module+2+b8645bbb"
|
||||
|
||||
build_two = models.ModuleBuild.get_by_id(db_session, 3)
|
||||
release_two = module_build_service.utils.get_rpm_release(db_session, build_two)
|
||||
assert release_two == "module+2+17e35784"
|
||||
|
||||
def test_get_rpm_release_platform_stream(self):
|
||||
scheduler_init_data(1)
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release = module_build_service.utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "module+f28+2+814cfa39"
|
||||
|
||||
def test_get_rpm_release_platform_stream_override(self):
|
||||
scheduler_init_data(1)
|
||||
|
||||
# Set the disttag_marking override on the platform
|
||||
platform = (
|
||||
db_session.query(models.ModuleBuild)
|
||||
.filter_by(name="platform", stream="f28")
|
||||
.first()
|
||||
)
|
||||
platform_mmd = platform.mmd()
|
||||
platform_xmd = platform_mmd.get_xmd()
|
||||
platform_xmd["mbs"]["disttag_marking"] = "fedora28"
|
||||
platform_mmd.set_xmd(platform_xmd)
|
||||
platform.modulemd = mmd_to_str(platform_mmd)
|
||||
db_session.add(platform)
|
||||
db_session.commit()
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release = module_build_service.utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "module+fedora28+2+814cfa39"
|
||||
|
||||
@patch(
|
||||
"module_build_service.config.Config.allowed_privileged_module_names",
|
||||
new_callable=mock.PropertyMock,
|
||||
return_value=["build"],
|
||||
)
|
||||
def test_get_rpm_release_metadata_br_stream_override(self, mock_admmn):
|
||||
"""
|
||||
Test that when a module buildrequires a module in conf.allowed_privileged_module_names,
|
||||
and that module has the xmd.mbs.disttag_marking field set, it should influence the disttag.
|
||||
"""
|
||||
scheduler_init_data(1)
|
||||
metadata_mmd = load_mmd(read_staged_data("build_metadata_module"))
|
||||
module_build_service.utils.import_mmd(db_session, metadata_mmd)
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
mmd = build_one.mmd()
|
||||
deps = mmd.get_dependencies()[0]
|
||||
deps.add_buildtime_stream("build", "product1.2")
|
||||
xmd = mmd.get_xmd()
|
||||
xmd["mbs"]["buildrequires"]["build"] = {
|
||||
"filtered_rpms": [],
|
||||
"ref": "virtual",
|
||||
"stream": "product1.2",
|
||||
"version": "1",
|
||||
"context": "00000000",
|
||||
}
|
||||
mmd.set_xmd(xmd)
|
||||
build_one.modulemd = mmd_to_str(mmd)
|
||||
db_session.add(build_one)
|
||||
db_session.commit()
|
||||
|
||||
release = module_build_service.utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "module+product12+2+814cfa39"
|
||||
|
||||
def test_get_rpm_release_mse_scratch(self):
|
||||
init_data(contexts=True, scratch=True)
|
||||
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release_one = module_build_service.utils.get_rpm_release(db_session, build_one)
|
||||
assert release_one == "scrmod+2+b8645bbb"
|
||||
|
||||
build_two = models.ModuleBuild.get_by_id(db_session, 3)
|
||||
release_two = module_build_service.utils.get_rpm_release(db_session, build_two)
|
||||
assert release_two == "scrmod+2+17e35784"
|
||||
|
||||
def test_get_rpm_release_platform_stream_scratch(self):
|
||||
scheduler_init_data(1, scratch=True)
|
||||
build_one = models.ModuleBuild.get_by_id(db_session, 2)
|
||||
release = module_build_service.utils.get_rpm_release(db_session, build_one)
|
||||
assert release == "scrmod+f28+2+814cfa39"
|
||||
|
||||
@patch("module_build_service.utils.submit.get_build_arches")
|
||||
def test_record_module_build_arches(self, get_build_arches):
|
||||
get_build_arches.return_value = ["x86_64", "i686"]
|
||||
@@ -695,125 +470,6 @@ class TestUtils:
|
||||
rv = get_reusable_component(new_module, "llvm", previous_module_build=old_module)
|
||||
assert rv.package == "llvm"
|
||||
|
||||
def test_validate_koji_tag_wrong_tag_arg_during_programming(self):
|
||||
""" Test that we fail on a wrong param name (non-existing one) due to
|
||||
programming error. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("wrong_tag_arg")
|
||||
def validate_koji_tag_programming_error(good_tag_arg, other_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ProgrammingError):
|
||||
validate_koji_tag_programming_error("dummy", "other_val")
|
||||
|
||||
def test_validate_koji_tag_bad_tag_value(self):
|
||||
""" Test that we fail on a bad tag value. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_bad_tag_value(tag_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validate_koji_tag_bad_tag_value("forbiddentagprefix-foo")
|
||||
|
||||
def test_validate_koji_tag_bad_tag_value_in_list(self):
|
||||
""" Test that we fail on a list containing bad tag value. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_bad_tag_value_in_list(tag_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validate_koji_tag_bad_tag_value_in_list(["module-foo", "forbiddentagprefix-bar"])
|
||||
|
||||
def test_validate_koji_tag_good_tag_value(self):
|
||||
""" Test that we pass on a good tag value. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_good_tag_value(tag_arg):
|
||||
return True
|
||||
|
||||
assert validate_koji_tag_good_tag_value("module-foo") is True
|
||||
|
||||
def test_validate_koji_tag_good_tag_values_in_list(self):
|
||||
""" Test that we pass on a list of good tag values. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_good_tag_values_in_list(tag_arg):
|
||||
return True
|
||||
|
||||
assert validate_koji_tag_good_tag_values_in_list(["module-foo", "module-bar"]) is True
|
||||
|
||||
def test_validate_koji_tag_good_tag_value_in_dict(self):
|
||||
""" Test that we pass on a dict arg with default key
|
||||
and a good value. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_good_tag_value_in_dict(tag_arg):
|
||||
return True
|
||||
|
||||
assert validate_koji_tag_good_tag_value_in_dict({"name": "module-foo"}) is True
|
||||
|
||||
def test_validate_koji_tag_good_tag_value_in_dict_nondefault_key(self):
|
||||
""" Test that we pass on a dict arg with non-default key
|
||||
and a good value. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg", dict_key="nondefault")
|
||||
def validate_koji_tag_good_tag_value_in_dict_nondefault_key(tag_arg):
|
||||
return True
|
||||
|
||||
assert (
|
||||
validate_koji_tag_good_tag_value_in_dict_nondefault_key({"nondefault": "module-foo"})
|
||||
is True
|
||||
)
|
||||
|
||||
def test_validate_koji_tag_double_trouble_good(self):
|
||||
""" Test that we pass on a list of tags that are good. """
|
||||
|
||||
expected = "foo"
|
||||
|
||||
@module_build_service.utils.validate_koji_tag(["tag_arg1", "tag_arg2"])
|
||||
def validate_koji_tag_double_trouble(tag_arg1, tag_arg2):
|
||||
return expected
|
||||
|
||||
actual = validate_koji_tag_double_trouble("module-1", "module-2")
|
||||
assert actual == expected
|
||||
|
||||
def test_validate_koji_tag_double_trouble_bad(self):
|
||||
""" Test that we fail on a list of tags that are bad. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag(["tag_arg1", "tag_arg2"])
|
||||
def validate_koji_tag_double_trouble(tag_arg1, tag_arg2):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
validate_koji_tag_double_trouble("module-1", "BADNEWS-2")
|
||||
|
||||
def test_validate_koji_tag_is_None(self):
|
||||
""" Test that we fail on a tag which is None. """
|
||||
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_is_None(tag_arg):
|
||||
pass
|
||||
|
||||
with pytest.raises(ValidationError) as cm:
|
||||
validate_koji_tag_is_None(None)
|
||||
assert str(cm.value).endswith(" No value provided.") is True
|
||||
|
||||
@patch(
|
||||
"module_build_service.config.Config.allowed_privileged_module_names",
|
||||
new_callable=mock.PropertyMock,
|
||||
return_value=["testmodule"],
|
||||
)
|
||||
def test_validate_koji_tag_previleged_module_name(self, conf_apmn):
|
||||
@module_build_service.utils.validate_koji_tag("tag_arg")
|
||||
def validate_koji_tag_priv_mod_name(self, tag_arg):
|
||||
pass
|
||||
|
||||
builder = mock.MagicMock()
|
||||
builder.module_str = 'testmodule'
|
||||
validate_koji_tag_priv_mod_name(builder, "abc")
|
||||
|
||||
@patch("module_build_service.scm.SCM")
|
||||
def test_record_component_builds_duplicate_components(self, mocked_scm):
|
||||
# Mock for format_mmd to get components' latest ref
|
||||
@@ -1005,22 +661,6 @@ class TestUtils:
|
||||
|
||||
assert build.time_modified == test_datetime
|
||||
|
||||
def test_generate_koji_tag_in_nsvc_format(self):
|
||||
name, stream, version, context = ("testmodule", "master", "20170816080815", "37c6c57")
|
||||
|
||||
tag = module_build_service.utils.generate_koji_tag(name, stream, version, context)
|
||||
|
||||
assert tag == "module-testmodule-master-20170816080815-37c6c57"
|
||||
|
||||
def test_generate_koji_tag_in_hash_format(self):
|
||||
name, version, context = ("testmodule", "20170816080815", "37c6c57")
|
||||
stream = "this-is-a-stream-with-very-looooong-name" + "-blah" * 50
|
||||
nsvc_list = [name, stream, version, context]
|
||||
|
||||
tag = module_build_service.utils.generate_koji_tag(*nsvc_list)
|
||||
expected_tag = "module-1cf457d452e54dda"
|
||||
assert tag == expected_tag
|
||||
|
||||
@patch("module_build_service.utils.submit.requests")
|
||||
def test_pdc_eol_check(self, requests):
|
||||
""" Push mock pdc responses through the eol check function. """
|
||||
@@ -1184,68 +824,6 @@ class TestLocalBuilds:
|
||||
assert local_modules[0].koji_tag.endswith("/module-platform-f28-3/results")
|
||||
|
||||
|
||||
class TestOfflineLocalBuilds:
|
||||
def setup_method(self):
|
||||
clean_database()
|
||||
|
||||
def teardown_method(self):
|
||||
clean_database()
|
||||
|
||||
def test_import_fake_base_module(self):
|
||||
module_build_service.utils.import_fake_base_module("platform:foo:1:000000")
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "platform", "foo", 1, "000000")
|
||||
assert module_build
|
||||
|
||||
mmd = module_build.mmd()
|
||||
xmd = mmd.get_xmd()
|
||||
assert xmd == {
|
||||
"mbs": {
|
||||
"buildrequires": {},
|
||||
"commit": "ref_000000",
|
||||
"koji_tag": "repofile://",
|
||||
"mse": "true",
|
||||
"requires": {},
|
||||
}
|
||||
}
|
||||
|
||||
assert set(mmd.get_profile_names()) == {"buildroot", "srpm-buildroot"}
|
||||
|
||||
@patch("module_build_service.utils.general.open", create=True, new_callable=mock.mock_open)
|
||||
def test_import_builds_from_local_dnf_repos(self, patched_open):
|
||||
with patch("dnf.Base") as dnf_base:
|
||||
repo = mock.MagicMock()
|
||||
repo.repofile = "/etc/yum.repos.d/foo.repo"
|
||||
mmd = load_mmd(read_staged_data("formatted_testmodule"))
|
||||
repo.get_metadata_content.return_value = mmd_to_str(mmd)
|
||||
base = dnf_base.return_value
|
||||
base.repos = {"reponame": repo}
|
||||
patched_open.return_value.readlines.return_value = ("FOO=bar", "PLATFORM_ID=platform:x")
|
||||
|
||||
module_build_service.utils.import_builds_from_local_dnf_repos()
|
||||
|
||||
base.read_all_repos.assert_called_once()
|
||||
repo.load.assert_called_once()
|
||||
repo.get_metadata_content.assert_called_once_with("modules")
|
||||
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "testmodule", "master", 20180205135154, "9c690d0e")
|
||||
assert module_build
|
||||
assert module_build.koji_tag == "repofile:///etc/yum.repos.d/foo.repo"
|
||||
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "platform", "x", 1, "000000")
|
||||
assert module_build
|
||||
|
||||
def test_import_builds_from_local_dnf_repos_platform_id(self):
|
||||
with patch("dnf.Base"):
|
||||
module_build_service.utils.import_builds_from_local_dnf_repos("platform:y")
|
||||
|
||||
module_build = models.ModuleBuild.get_build_from_nsvc(
|
||||
db_session, "platform", "y", 1, "000000")
|
||||
assert module_build
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("reuse_component_init_data")
|
||||
class TestUtilsModuleReuse:
|
||||
|
||||
@@ -1310,7 +888,7 @@ class TestUtilsModuleReuse:
|
||||
xmd = mmd.get_xmd()
|
||||
xmd["mbs"]["virtual_streams"] = ["fedora"]
|
||||
mmd.set_xmd(xmd)
|
||||
platform_f29 = module_build_service.utils.import_mmd(db_session, mmd)[0]
|
||||
platform_f29 = import_mmd(db_session, mmd)[0]
|
||||
|
||||
# Create another copy of `testmodule:master` which should be reused, because its
|
||||
# stream version will be higher than the previous one. Also set its buildrequires
|
||||
@@ -1399,7 +977,7 @@ class TestUtilsModuleReuse:
|
||||
xmd = mmd.get_xmd()
|
||||
xmd["mbs"]["virtual_streams"] = ["fedora"]
|
||||
mmd.set_xmd(xmd)
|
||||
platform_f27 = module_build_service.utils.import_mmd(db_session, mmd)[0]
|
||||
platform_f27 = import_mmd(db_session, mmd)[0]
|
||||
|
||||
# Change the reusable testmodule:master to buildrequire platform:f27.
|
||||
latest_module = db_session.query(models.ModuleBuild).filter_by(
|
||||
|
||||
@@ -4,6 +4,7 @@ from mock import patch, PropertyMock
|
||||
import pytest
|
||||
|
||||
import module_build_service.utils
|
||||
from module_build_service.common.utils import load_mmd
|
||||
from module_build_service import Modulemd, models
|
||||
from module_build_service.db_session import db_session
|
||||
from module_build_service.errors import StreamAmbigous
|
||||
@@ -470,7 +471,7 @@ class TestUtilsModuleStreamExpansion:
|
||||
def test__get_base_module_mmds(self):
|
||||
"""Ensure the correct results are returned without duplicates."""
|
||||
init_data(data_size=1, multiple_stream_versions=True)
|
||||
mmd = module_build_service.utils.load_mmd(read_staged_data("testmodule_v2.yaml"))
|
||||
mmd = load_mmd(read_staged_data("testmodule_v2.yaml"))
|
||||
deps = mmd.get_dependencies()[0]
|
||||
new_deps = Modulemd.Dependencies()
|
||||
for stream in deps.get_runtime_streams("platform"):
|
||||
@@ -494,7 +495,7 @@ class TestUtilsModuleStreamExpansion:
|
||||
def test__get_base_module_mmds_virtual_streams(self, virtual_streams):
|
||||
"""Ensure the correct results are returned without duplicates."""
|
||||
init_data(data_size=1, multiple_stream_versions=True)
|
||||
mmd = module_build_service.utils.load_mmd(read_staged_data("testmodule_v2"))
|
||||
mmd = load_mmd(read_staged_data("testmodule_v2"))
|
||||
deps = mmd.get_dependencies()[0]
|
||||
new_deps = Modulemd.Dependencies()
|
||||
for stream in deps.get_runtime_streams("platform"):
|
||||
@@ -538,7 +539,7 @@ class TestUtilsModuleStreamExpansion:
|
||||
db_session.add(platform)
|
||||
db_session.commit()
|
||||
|
||||
mmd = module_build_service.utils.load_mmd(read_staged_data("testmodule_v2"))
|
||||
mmd = load_mmd(read_staged_data("testmodule_v2"))
|
||||
deps = mmd.get_dependencies()[0]
|
||||
new_deps = Modulemd.Dependencies()
|
||||
for stream in deps.get_runtime_streams("platform"):
|
||||
|
||||
@@ -18,6 +18,8 @@ import pytest
|
||||
import re
|
||||
import sqlalchemy
|
||||
|
||||
from module_build_service.builder.utils import get_rpm_release
|
||||
from module_build_service.common.utils import load_mmd, import_mmd, mmd_to_str
|
||||
from tests import (
|
||||
init_data,
|
||||
clean_database,
|
||||
@@ -33,9 +35,6 @@ from module_build_service.models import ModuleBuild, BUILD_STATES, ComponentBuil
|
||||
from module_build_service import app, version
|
||||
import module_build_service.config as mbs_config
|
||||
import module_build_service.utils.submit
|
||||
from module_build_service.utils.general import (
|
||||
import_mmd, mmd_to_str, load_mmd,
|
||||
get_rpm_release)
|
||||
|
||||
|
||||
user = ("Homer J. Simpson", {"packager"})
|
||||
|
||||
Reference in New Issue
Block a user