Merge #1667 Added the support for the new libmodulemd v3 packager format.

This commit is contained in:
Brendan Reilly
2021-03-03 14:26:56 +00:00
10 changed files with 512 additions and 135 deletions

View File

@@ -3,7 +3,6 @@
"""SCM handler functions."""
from __future__ import absolute_import
import datetime
import os
import subprocess as sp
import re
@@ -18,6 +17,7 @@ from module_build_service.common.errors import (
ProgrammingError,
)
from module_build_service.common.retry import retry
from module_build_service.common.utils import provide_module_stream_version_from_timestamp
def scm_url_schemes(terse=False):
@@ -229,8 +229,7 @@ class SCM(object):
raise
timestamp = SCM._run(["git", "show", "-s", "--format=%ct"], chdir=self.sourcedir)[1]
dt = datetime.datetime.utcfromtimestamp(int(timestamp))
self.version = dt.strftime("%Y%m%d%H%M%S")
self.version = provide_module_stream_version_from_timestamp(timestamp=timestamp)
else:
raise RuntimeError("checkout: Unhandled SCM scheme.")
return self.sourcedir

View File

@@ -88,12 +88,10 @@ def fetch_mmd(url, branch=None, allow_local_url=False, whitelist_url=False, mand
# If the version is in the modulemd, throw an exception since the version
# since the version is generated by MBS
if mmd.get_version():
if mmd.get_mdversion() == 2 and mmd.get_version():
raise ValidationError(
'The version "{0}" is already defined in the modulemd but it shouldn\'t be since the '
"version is generated based on the commit time".format(mmd.get_version())
)
else:
mmd.set_version(int(scm.version))
return mmd, scm

View File

@@ -4,6 +4,7 @@ from __future__ import absolute_import
from datetime import datetime
from functools import partial
import os
import time
from gi.repository.GLib import Error as ModuleMDError
from six import string_types, text_type
@@ -27,44 +28,37 @@ def load_mmd(yaml, is_file=False):
if not yaml:
raise UnprocessableEntity('The input modulemd was empty')
target_mmd_version = Modulemd.ModuleStreamVersionEnum.TWO
try:
if is_file:
mmd = Modulemd.ModuleStream.read_file(yaml, True)
mmd = Modulemd.read_packager_file(yaml)
else:
mmd = Modulemd.ModuleStream.read_string(to_text_type(yaml), True)
mmd.validate()
if mmd.get_mdversion() < target_mmd_version:
mmd = mmd.upgrade(target_mmd_version)
elif mmd.get_mdversion() > target_mmd_version:
log.error("Encountered a modulemd file with the version %d", mmd.get_mdversion())
raise UnprocessableEntity(
"The modulemd version cannot be greater than {}".format(target_mmd_version))
mmd = Modulemd.read_packager_string(to_text_type(yaml))
mmd_version = mmd.get_mdversion()
# both legacy packager v1 and stream v1 are directly upgraded to v2
if mmd_version == 1:
mmd = mmd.upgrade(2)
except ModuleMDError as e:
not_found = False
error = None
if is_file:
error = "The modulemd {} is invalid.".format(os.path.basename(yaml))
if os.path.exists(yaml):
with open(yaml, "rt") as yaml_hdl:
log.debug("Modulemd that failed to load:\n%s", yaml_hdl.read())
log.debug("The modulemd file '%s' failed to load:\n%s",
yaml,
yaml_hdl.read())
else:
not_found = True
error = "The modulemd file {} was not found.".format(os.path.basename(yaml))
error = "The modulemd file {} was not found.".format(yaml)
log.error("The modulemd file %s was not found.", yaml)
else:
error = "The modulemd is invalid."
log.debug("Modulemd that failed to load:\n%s", yaml)
if "modulemd-error-quark: " in str(e):
error = "{} The error was '{}'.".format(
error, str(e).split("modulemd-error-quark: ")[-1])
elif "Unknown ModuleStream version" in str(e):
error = (
"{}. The modulemd version can't be greater than {}."
.format(error, target_mmd_version)
)
elif not_found is False:
error = "{} Please verify the syntax is correct.".format(error)
if not error:
if is_file:
error = ("The modulemd {} is invalid. The error was:\n'{}'\nPlease verify the"
" syntax is correct.").format(os.path.basename(yaml), str(e))
else:
error = ("The modulemd is invalid. The error was:\n'{}'\nPlease verify the"
" syntax is correct.").format(str(e))
log.exception(error)
raise UnprocessableEntity(error)
@@ -226,3 +220,39 @@ def mmd_to_str(mmd):
index = Modulemd.ModuleIndex()
index.add_module_stream(mmd)
return to_text_type(index.dump_to_string())
def provide_module_stream_version_from_timestamp(timestamp=None):
"""
Provides a module stream version from a unix timestamp. If the timestamp is not defined
it will will generate one..
:param timestamp: modulemd object representing module metadata.
:type mmd: Modulemd.Module
:return: module stream version
:rtype: int
"""
if timestamp:
dt = datetime.utcfromtimestamp(int(timestamp))
else:
dt = datetime.utcfromtimestamp(int(time.time()))
return int(dt.strftime("%Y%m%d%H%M%S"))
def provide_module_stream_version_from_mmd(mmd):
"""
Provides a module stream version for a module stream. If a mmd v2 already contains
a version it will return it else it will generate a new one.
:param mmd: modulemd object representing module metadata.
:type mmd: Modulemd.Module
:return: module stream version
:rtype: int
"""
if mmd.get_mdversion() == 2 and mmd.get_version():
return mmd.get_version()
dt = datetime.utcfromtimestamp(int(time.time()))
return int(dt.strftime("%Y%m%d%H%M%S"))

View File

@@ -6,7 +6,6 @@ from datetime import datetime
import math
import os
import re
import time
from gi.repository import GLib
import requests
@@ -16,7 +15,8 @@ from module_build_service.common.errors import Conflict, Forbidden, ValidationEr
from module_build_service.common.messaging import notify_on_module_state_change
from module_build_service.common.modulemd import Modulemd
from module_build_service.common.submit import fetch_mmd
from module_build_service.common.utils import load_mmd, mmd_to_str, to_text_type
from module_build_service.common.utils import (load_mmd, mmd_to_str, to_text_type,
provide_module_stream_version_from_mmd)
from module_build_service.web.mse import generate_expanded_mmds, generate_mmds_from_static_contexts
from module_build_service.web.utils import deps_to_dict
@@ -47,7 +47,7 @@ def validate_mmd(mmd):
if name not in conf.allowed_privileged_module_names:
raise ValidationError('The "mbs" xmd field is reserved for MBS')
allowed_keys = ["disttag_marking", "koji_tag_arches"]
allowed_keys = ["disttag_marking", "koji_tag_arches", 'static_context']
for key in xmd["mbs"].keys():
if key not in allowed_keys:
raise ValidationError('The "mbs" xmd field is reserved for MBS')
@@ -112,7 +112,6 @@ def submit_module_build_from_yaml(
):
yaml_file = to_text_type(handle.read())
mmd = load_mmd(yaml_file)
dt = datetime.utcfromtimestamp(int(time.time()))
if hasattr(handle, "filename"):
def_name = str(os.path.splitext(os.path.basename(handle.filename))[0])
elif not mmd.get_module_name():
@@ -120,19 +119,20 @@ def submit_module_build_from_yaml(
"The module's name was not present in the modulemd file. Please use the "
'"module_name" parameter'
)
def_version = int(dt.strftime("%Y%m%d%H%M%S"))
module_name = mmd.get_module_name() or def_name
module_stream = stream or mmd.get_stream_name() or "master"
if module_name != mmd.get_module_name() or module_stream != mmd.get_stream_name():
# This is how you set the name and stream in the modulemd
mmd = mmd.copy(module_name, module_stream)
mmd.set_version(mmd.get_version() or def_version)
if skiptests:
buildopts = mmd.get_buildopts() or Modulemd.Buildopts()
macros = buildopts.get_rpm_macros() or ""
buildopts.set_rpm_macros(macros + "\n\n%__spec_check_pre exit 0\n")
mmd.set_buildopts(buildopts)
return submit_module_build(db_session, username, mmd, params)
module_stream_version = provide_module_stream_version_from_mmd(mmd)
return submit_module_build(db_session, username, mmd, params, module_stream_version)
_url_check_re = re.compile(r"^[^:/]+:.*$")
@@ -148,7 +148,9 @@ def submit_module_build_from_scm(db_session, username, params, allow_local_url=F
url = "file://" + url
mmd, scm = fetch_mmd(url, branch, allow_local_url)
return submit_module_build(db_session, username, mmd, params)
module_stream_version = int(scm.version)
return submit_module_build(db_session, username, mmd, params, module_stream_version)
def _apply_dep_overrides(mmd, params):
@@ -521,7 +523,7 @@ def _process_support_streams(db_session, mmd, params):
_modify_buildtime_streams(db_session, mmd, new_streams_func)
def submit_module_build(db_session, username, mmd, params):
def submit_module_build(db_session, username, mmd, params, module_stream_version):
"""
Submits new module build.
@@ -532,13 +534,6 @@ def submit_module_build(db_session, username, mmd, params):
:rtype: list with ModuleBuild
:return: List with submitted module builds.
"""
log.debug(
"Submitted %s module build for %s:%s:%s",
("scratch" if params.get("scratch", False) else "normal"),
mmd.get_module_name(),
mmd.get_stream_name(),
mmd.get_version(),
)
raise_if_stream_ambigous = False
default_streams = {}
@@ -550,11 +545,18 @@ def submit_module_build(db_session, username, mmd, params):
if "default_streams" in params:
default_streams = params["default_streams"]
xmd = mmd.get_xmd()
# we check if static contexts are enabled by the `contexts` property defined by the user i
# as an build option.
static_context = "mbs_options" in xmd and "contexts" in xmd["mbs_options"]
input_mmds = generate_mmds_from_static_contexts(mmd) if static_context else [mmd]
input_mmds, static_context = process_module_context_configuration(mmd)
for mmd in input_mmds:
mmd.set_version(module_stream_version)
log.debug(
"Submitted %s module build for %s:%s:%s",
("scratch" if params.get("scratch", False) else "normal"),
input_mmds[0].get_module_name(),
input_mmds[0].get_stream_name(),
input_mmds[0].get_version(),
)
mmds = []
for mmd in input_mmds:
@@ -690,3 +692,62 @@ def submit_module_build(db_session, username, mmd, params):
raise Conflict(err_msg)
return modules
def process_module_context_configuration(mmd):
"""
Processes initial module metadata context configurations and creates individual module
metadata for each context, if static context configuration is present.
:param Modulemd.ModuleStream packager_mmd: Packager (initial) modulemd which kickstarts
the build.
:rtype: list with ModuleBuild
:return: list of generated module metadata from context configurations.
"""
mdversion = mmd.get_mdversion()
static_context = False
# we check what version of the metadata format we are using.
if mdversion == 3:
# v3 we always talking about a new build and the static context
# will be always True
static_context = True
mdindex = mmd.convert_to_index()
streams = mdindex.search_streams()
for stream in streams:
if not stream.is_static_context():
stream.set_static_context()
# we get the dependenices of the stream
deps = stream.get_dependencies()
# with v3 packager format the output v2 stream will always have
# only one set of dependecies. We need to remove the platform
# virtual module from runtime dependencies as it is not desired.
modules = deps[0].get_runtime_modules()
module_streams = [(m, deps[0].get_runtime_streams(m)[0]) for m in modules
if m not in conf.base_module_names]
deps[0].clear_runtime_dependencies()
for module_stream in module_streams:
module, stream = module_stream
deps[0].add_runtime_stream(module, stream)
return streams, static_context
else:
xmd = mmd.get_xmd()
# check if we are handling rebuild of a static context module
if "mbs" in xmd:
# check if it is a static context
if "static_context" in xmd["mbs"] or mmd.is_static_context():
static_context = True
return [mmd], static_context
# we check if static contexts are enabled by the `contexts` property defined by the user i
# as an build option.
static_context = "mbs_options" in xmd and "contexts" in xmd["mbs_options"]
# if the static context configuration exists we expand it. If not we just return
# the mmd unchanged, for futher processing.
streams = generate_mmds_from_static_contexts(mmd) if static_context else [mmd]
return streams, static_context

View File

@@ -0,0 +1,32 @@
document: modulemd
version: 2
data:
name: app
stream: test
summary: "A test module"
description: >
"A test module stream"
license:
module: [ MIT ]
dependencies:
- buildrequires:
platform: []
gtk: []
requires:
platform: []
gtk: []
xmd:
mbs_options:
contexts:
context1:
buildrequires:
platform: f28
requires:
platform: f28
gtk: 1
context2:
buildrequires:
platform: f28
requires:
platform: f28
gtk: 2

View File

@@ -0,0 +1,41 @@
document: modulemd-packager
# Module metadata format version
version: 3
data:
name: foo
stream: latest
summary: An example module
description: >-
A module for the demonstration of the metadata format. Also,
the obligatory lorem ipsum dolor sit amet goes right here.
license:
- MIT
xmd:
some_key: some_data
configurations:
- context: CTX1
platform: f28
requires:
nginx: [1]
- context: CTX2
platform: f29
references:
community: http://www.example.com/
documentation: http://www.example.com/
tracker: http://www.example.com/
profiles:
container:
rpms:
- foo
api:
rpms:
- foo
components:
rpms:
foo:
name: foo
rationale: We need this to demonstrate stuff.
repository: https://pagure.io/foo.git
cache: https://example.com/cache
ref: 26ca0c0

View File

@@ -203,10 +203,10 @@ class TestBuild:
assert len(mmd.read()) == 1271
with io.open(path.join(dir_path, "modulemd.x86_64.txt"), encoding="utf-8") as mmd:
assert len(mmd.read()) == 349
assert len(mmd.read()) == 351
with io.open(path.join(dir_path, "modulemd.i686.txt"), encoding="utf-8") as mmd:
assert len(mmd.read()) == 347
assert len(mmd.read()) == 349
@patch("koji.ClientSession")
def test_tag_cg_build(self, ClientSession):
@@ -318,7 +318,7 @@ class TestBuild:
assert ret == {
"arch": "x86_64",
"buildroot_id": 1,
"checksum": "580e1f880e0872bed58591c55eeb6e7e",
"checksum": "3b4b748bd14ae440176a6ea1fe649218",
"checksum_type": "md5",
"components": [
{
@@ -333,7 +333,7 @@ class TestBuild:
],
"extra": {"typeinfo": {"module": {}}},
"filename": "modulemd.x86_64.txt",
"filesize": 409,
"filesize": 411,
"type": "file",
}

View File

@@ -1,14 +1,17 @@
# -*- 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
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
from tests import read_staged_data, staged_data_filename
@pytest.mark.parametrize("context", ["c1", None])
@@ -151,3 +154,136 @@ def test_import_mmd_dont_remove_dropped_virtual_streams_associated_with_other_mo
# 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

View File

@@ -12,15 +12,19 @@ from werkzeug.datastructures import FileStorage
from module_build_service.common import models
from module_build_service.common.errors import ValidationError
from module_build_service.common.utils import mmd_to_str, load_mmd
from module_build_service.common.utils import (mmd_to_str, load_mmd,
provide_module_stream_version_from_timestamp)
from module_build_service.scheduler.db_session import db_session
from module_build_service.web.submit import (
get_prefixed_version, submit_module_build, submit_module_build_from_yaml
get_prefixed_version, submit_module_build, submit_module_build_from_yaml,
process_module_context_configuration
)
from tests import (
scheduler_init_data,
make_module_in_db,
make_module,
read_staged_data,
init_data,
)
@@ -50,43 +54,12 @@ class TestSubmit:
is set to False.
"""
yaml_str = """
document: modulemd
version: 2
data:
name: app
stream: test
summary: "A test module"
description: >
"A test module stream"
license:
module: [ MIT ]
dependencies:
- buildrequires:
platform: []
gtk: []
requires:
platform: []
gtk: []
xmd:
mbs_options:
contexts:
context1:
buildrequires:
platform: f28
requires:
platform: f28
gtk: 1
context2:
buildrequires:
platform: f28
requires:
platform: f28
gtk: 2
"""
yaml_str = read_staged_data("static_context_v2")
mmd = load_mmd(yaml_str)
builds = submit_module_build(db_session, "app", mmd, {})
ux_timestamp = "1613048427"
version = provide_module_stream_version_from_timestamp(ux_timestamp)
builds = submit_module_build(db_session, "app", mmd, {}, version)
expected_context = ["context1", "context2"]
@@ -96,6 +69,7 @@ data:
assert build.context in expected_context
mmd = build.mmd()
xmd = mmd.get_xmd()
assert mmd.get_version() == int("28" + str(version))
assert "mbs_options" not in xmd
assert xmd["mbs"]["static_context"]
@@ -105,38 +79,19 @@ data:
are more options configured then `contexts` option..
"""
yaml_str = """
document: modulemd
version: 2
data:
name: app
stream: test1
summary: "A test module"
description: >
"A test module stream"
license:
module: [ MIT ]
dependencies:
- buildrequires:
platform: []
gtk: []
requires:
platform: []
gtk: []
xmd:
mbs_options:
contexts:
context1:
buildrequires:
platform: f28
requires:
platform: f28
gtk: 1
another_option: "test"
"""
yaml_str = read_staged_data("static_context_v2")
mmd = load_mmd(yaml_str)
xmd = mmd.get_xmd()
xmd["mbs_options"]["another_option"] = "test"
xmd["mbs_options"]["contexts"] = {
"context3": xmd["mbs_options"]["contexts"]["context1"]
}
mmd.set_xmd(xmd)
builds = submit_module_build(db_session, "app", mmd, {})
ux_timestamp = "1613048427"
version = provide_module_stream_version_from_timestamp(ux_timestamp)
builds = submit_module_build(db_session, "app", mmd, {}, version)
assert len(builds) == 1
mmd = builds[0].mmd()
@@ -145,6 +100,123 @@ data:
assert "another_option" in xmd["mbs_options"]
assert "test" == xmd["mbs_options"]["another_option"]
def test_submit_build_module_context_configurations(self):
"""
With the introduction of the v3 packager yaml format we replace MSE with static contexts.
This test tests the submission of such a packager file.
"""
init_data(multiple_stream_versions=True)
yaml_str = read_staged_data("v3/mmd_packager")
mmd = load_mmd(yaml_str)
ux_timestamp = "1613048427"
version = provide_module_stream_version_from_timestamp(ux_timestamp)
builds = submit_module_build(db_session, "foo", mmd, {}, version)
assert len(builds) == 2
expected_deps = {"CTX1": {"buildrequires": {"platform": ["f28"]},
"requires": {"nginx": ["1"]}},
"CTX2": {"buildrequires": {"platform": ["f29.2.0"]},
"requires": {}}}
for build in builds:
mmd = build.mmd()
context = mmd.get_context()
assert context in expected_deps
assert mmd.get_mdversion() == 2
deps = mmd.get_dependencies()[0]
btms = deps.get_buildtime_modules()
rtms = deps.get_runtime_modules()
for btm in btms:
expected_stream = expected_deps[context]["buildrequires"][btm][0]
actual_stream = deps.get_buildtime_streams(btm)[0]
assert expected_stream == actual_stream
for rtm in rtms:
expected_stream = expected_deps[context]["requires"][rtm][0]
actual_stream = deps.get_runtime_streams(rtm)[0]
assert expected_stream == actual_stream
xmd = mmd.get_xmd()
assert "mbs_options" not in xmd
assert xmd["mbs"]["static_context"]
class TestProcessModuleContextConfiguration:
"""
With the introduction of static contexts, we have now several different configuration of
static contexts for different major/minor RHEL releases.
"""
def test_process_mse_configuration(self):
"""
Testing the processing of MSE type packager (v2) file i. e. no static context.
"""
yaml_str = read_staged_data("static_context_v2")
mmd = load_mmd(yaml_str)
mmd.set_xmd({})
streams, static_context = process_module_context_configuration(mmd)
assert not static_context
assert len(streams) == 1
assert not mmd.get_context()
def test_process_initial_xmd_static_configuration(self):
"""
Testing the processing of MSE type packager (v2) file with static context
configuration in XMD
"""
yaml_str = read_staged_data("static_context_v2")
mmd = load_mmd(yaml_str)
streams, static_context = process_module_context_configuration(mmd)
assert static_context
assert len(streams) == 2
expected_contexts = ["context1", "context2"]
for stream in streams:
assert stream.get_context() in expected_contexts
def test_process_xmd_static_context_rebuild(self):
"""
Testing the processing of MSE type file (v2) used for rebuild with set static_context in
mbs metadata in xmd.
"""
yaml_str = read_staged_data("testmodule_v2")
mmd = load_mmd(yaml_str)
mmd.set_context("context1")
mmd.set_xmd({"mbs": {"static_context": True}})
streams, static_context = process_module_context_configuration(mmd)
assert static_context
assert len(streams) == 1
assert streams[0].get_context() == "context1"
def test_process_v3_packager_file(self):
"""
Testing the processing of v3 packager file with static context configurations.
"""
yaml_str = read_staged_data("v3/mmd_packager")
mmd = load_mmd(yaml_str)
streams, static_context = process_module_context_configuration(mmd)
assert static_context
assert len(streams) == 2
expected_contexts = ["CTX1", "CTX2"]
for stream in streams:
assert stream.get_mdversion() == 2
assert stream.get_context() in expected_contexts
assert stream.is_static_context()
@pytest.mark.usefixtures("reuse_component_init_data")
class TestUtilsComponentReuse:
@@ -200,10 +272,13 @@ class TestUtilsComponentReuse:
mmd1_copy = mmd1.copy()
mmd1_copy.set_xmd({})
builds = submit_module_build(db_session, "foo", mmd1_copy, {})
ret = {b.mmd().get_context(): b.state for b in builds}
assert ret == {"c1": models.BUILD_STATES["ready"], "c2": models.BUILD_STATES["init"]}
ux_timestamp = "1613048427"
version = provide_module_stream_version_from_timestamp(ux_timestamp)
builds = submit_module_build(db_session, "foo", mmd1_copy, {}, version)
ret = {b.mmd().get_context(): b.state for b in builds}
assert ret == {"c1": models.BUILD_STATES["ready"], "c2": models.BUILD_STATES["init"]}
assert builds[0].siblings(db_session) == [builds[1].id]
assert builds[1].siblings(db_session) == [builds[0].id]
@@ -223,10 +298,13 @@ class TestUtilsComponentReuse:
mmd_copy = mmd.copy()
mmd_copy.set_xmd({})
ux_timestamp = "1613048427"
version = provide_module_stream_version_from_timestamp(ux_timestamp)
with pytest.raises(
ValidationError,
match="Only scratch module builds can be built from this branch.",
):
submit_module_build(db_session, "foo", mmd_copy, {"branch": "private-foo"})
submit_module_build(db_session, "foo", mmd_copy, {"branch": "private-foo"}, version)
submit_module_build(db_session, "foo", mmd_copy, {"branch": "otherbranch"})
submit_module_build(db_session, "foo", mmd_copy, {"branch": "otherbranch"}, version)

View File

@@ -1259,9 +1259,10 @@ class TestSubmitBuild:
)
data = json.loads(rv.data)
assert re.match(
r"The modulemd .* is invalid\. Please verify the syntax is correct",
r"The modulemd .* is invalid\. ",
data["message"]
)
assert "Please verify the syntax is correct" in data["message"]
assert data["status"] == 422
assert data["error"] == "Unprocessable Entity"
@@ -2796,8 +2797,9 @@ class TestImportBuild:
assert data["error"] == "Unprocessable Entity"
assert re.match(
r"The modulemd .* is invalid\. Please verify the syntax is correct", data["message"]
r"The modulemd .* is invalid\. ", data["message"]
)
assert "Please verify the syntax is correct" in data["message"]
@pytest.mark.usefixtures("provide_test_client")