LNX-102: Patch pungi tool to use local koji mock

Instead of koji.mbox use local koji-like wrapper.

@BS-LINKED-5ff8b8cb6f44affc6c5e9a7a
@BS-TARGET-CL8

Change-Id: I82a2bc8bc71ae06240656898f3df71bb28bcb9e9
This commit is contained in:
oshyshatskyi 2020-12-29 12:45:45 +02:00
parent 552343fffe
commit 903db91c0f
8 changed files with 739 additions and 85 deletions

View File

@ -501,41 +501,19 @@ class KojiPackageSet(PackageSetBase):
if "path_from_task" in rpm_info: if "path_from_task" in rpm_info:
return rpm_info["path_from_task"] return rpm_info["path_from_task"]
# we replaced this part because pungi uses way
# of guessing path of package on koji based on sigkey
# we don't need that because all our packages will
# be ready for release
# signature verification is still done during deps resolution
pathinfo = self.koji_wrapper.koji_module.pathinfo pathinfo = self.koji_wrapper.koji_module.pathinfo
paths = []
for sigkey in self.sigkey_ordering:
if not sigkey:
# we're looking for *signed* copies here
continue
sigkey = sigkey.lower()
rpm_path = os.path.join(
pathinfo.build(build_info), pathinfo.signed(rpm_info, sigkey)
)
paths.append(rpm_path)
if os.path.isfile(rpm_path):
return rpm_path
if None in self.sigkey_ordering or "" in self.sigkey_ordering: rpm_path = os.path.join(pathinfo.topdir, pathinfo.rpm(rpm_info))
# use an unsigned copy (if allowed) if os.path.isfile(rpm_path):
rpm_path = os.path.join(pathinfo.build(build_info), pathinfo.rpm(rpm_info)) return rpm_path
paths.append(rpm_path) else:
if os.path.isfile(rpm_path): self.log_warning("RPM %s not found" % rpm_path)
return rpm_path return None
if self._allow_invalid_sigkeys and rpm_info["name"] not in self.packages:
# use an unsigned copy (if allowed)
rpm_path = os.path.join(pathinfo.build(build_info), pathinfo.rpm(rpm_info))
paths.append(rpm_path)
if os.path.isfile(rpm_path):
self._invalid_sigkey_rpms.append(rpm_info)
return rpm_path
self._invalid_sigkey_rpms.append(rpm_info)
self.log_error(
"RPM %s not found for sigs: %s. Paths checked: %s"
% (rpm_info, self.sigkey_ordering, paths)
)
return None
def populate(self, tag, event=None, inherit=True, include_packages=None): def populate(self, tag, event=None, inherit=True, include_packages=None):
"""Populate the package set with packages from given tag. """Populate the package set with packages from given tag.

View File

@ -28,7 +28,6 @@ import pungi.wrappers.kojiwrapper
from pungi.wrappers.comps import CompsWrapper from pungi.wrappers.comps import CompsWrapper
from pungi.wrappers.mbs import MBSWrapper from pungi.wrappers.mbs import MBSWrapper
import pungi.phases.pkgset.pkgsets import pungi.phases.pkgset.pkgsets
from pungi.arch import getBaseArch
from pungi.util import retry, get_arch_variant_data, get_variant_data from pungi.util import retry, get_arch_variant_data, get_variant_data
from pungi.module_util import Modulemd from pungi.module_util import Modulemd
@ -221,18 +220,10 @@ def _add_module_to_variant(
if archive["btype"] != "module": if archive["btype"] != "module":
# Skip non module archives # Skip non module archives
continue continue
typedir = koji_wrapper.koji_module.pathinfo.typedir(build, archive["btype"])
filename = archive["filename"] filename = archive["filename"]
file_path = os.path.join(typedir, filename) # TODO: add support for muplitple arches
try: file_path = os.path.join(koji_wrapper.koji_module.pathinfo.topdir, 'modules',
# If there are two dots, the arch is in the middle. MBS uploads build['extra']['typeinfo']['module']['content_koji_tag'])
# files with actual architecture in the filename, but Pungi deals
# in basearch. This assumes that each arch in the build maps to a
# unique basearch.
_, arch, _ = filename.split(".")
filename = "modulemd.%s.txt" % getBaseArch(arch)
except ValueError:
pass
mmds[filename] = file_path mmds[filename] = file_path
if len(mmds) <= 1: if len(mmds) <= 1:

296
pungi/wrappers/kojimock.py Normal file
View File

@ -0,0 +1,296 @@
import os
import subprocess
import time
from attr import dataclass
from kobo.rpmlib import parse_nvra
from pungi.module_util import Modulemd
# just a random value which we don't
# use in mock currently
# originally builds are filtered by this value
# to get consistent snapshot of tags and packages
from pungi.scripts.gather_rpms import search_rpms
LAST_EVENT_ID = 999999
# last event time is not important but build
# time should be less then it
LAST_EVENT_TIME = time.time()
BUILD_TIME = 0
# virtual build that collects all
# packages built for some arch
RELEASE_BUILD_ID = 15270
# tag that should have all packages available
ALL_PACKAGES_TAG = 'dist-c8-compose'
# tag that should have all modules available
ALL_MODULES_TAG = 'dist-c8-module-compose'
@dataclass
class Module:
build_id: int
name: str
nvr: str
stream: str
version: str
context: str
class KojiMock:
"""
Class that acts like real koji (for some needed methods)
but uses local storage as data source
"""
def __init__(self, packages_dir, modules_dir):
self._modules = self._gather_modules(modules_dir)
self._modules_dir = modules_dir
self._packages_dir = packages_dir
def _gather_modules(self, modules_dir):
modules = {}
for index, f in enumerate(os.listdir(modules_dir)):
parsed = parse_nvra(f)
modules[index] = Module(
name=parsed['name'],
nvr=f,
version=parsed['release'],
context=parsed['arch'],
stream=parsed['version'],
build_id=index
)
return modules
def getLastEvent(self, *args, **kwargs):
return {'id': LAST_EVENT_ID, 'ts': LAST_EVENT_TIME}
def listTagged(self, tag_name, *args, **kwargs):
"""
Returns list of virtual 'builds' that contain packages by given tag
There are two kinds of tags: modular and distributive.
For now, only one kind, distributive one, is needed.
"""
if tag_name != ALL_MODULES_TAG:
raise ValueError("I don't know what tag is %s" % tag_name)
builds = []
for module in self._modules.values():
builds.append({
'build_id': module.build_id,
'owner_name': 'centos',
'package_name': module.name,
'nvr': module.nvr,
'version': module.stream,
'release': '%s.%s' % (module.version, module.context),
'name': module.name,
'id': module.build_id,
'tag_name': tag_name,
# Following fields are currently not
# used but returned by real koji
# left them here just for reference
#
# 'task_id': None,
# 'state': 1,
# 'start_time': '2020-12-23 16:43:59',
# 'creation_event_id': 309485,
# 'creation_time': '2020-12-23 17:05:33.553748',
# 'epoch': None, 'tag_id': 533,
# 'completion_time': '2020-12-23 17:05:23',
# 'volume_id': 0,
# 'package_id': 3221,
# 'owner_id': 11,
# 'volume_name': 'DEFAULT',
})
return builds
def getFullInheritance(self, *args, **kwargs):
"""
Unneeded because we use local storage.
"""
return []
def getBuild(self, build_id, *args, **kwargs):
"""
Used to get information about build
(used in pungi only for modules currently)
"""
module = self._modules[build_id]
result = {
'id': build_id,
'name': module.name,
'version': module.stream,
'release': '%s.%s' % (module.version, module.context),
'completion_ts': BUILD_TIME,
'state': 'COMPLETE',
'extra': {
'typeinfo': {
'module': {
'stream': module.stream,
'version': module.version,
'name': module.name,
'context': module.context,
'content_koji_tag': '-'.join([
module.name,
module.stream,
module.version
]) + '.' + module.context
}
}
}
}
return result
def listArchives(self, build_id, *args, **kwargs):
"""
Originally lists artifacts for build, but in pungi used
only to get list of modulemd files for some module
"""
module = self._modules[build_id]
return [
{
'build_id': module.build_id,
'filename': 'modulemd.x86_64.txt',
'btype': 'module'
},
# noone ever uses this file
# but it should be because pungi ignores builds
# with len(files) <= 1
{
'build_id': module.build_id,
'filename': 'modulemd.txt',
'btype': 'module'
}
]
def listTaggedRPMS(self, tag_name, *args, **kwargs):
"""
Get information about packages that are tagged by tag.
There are two kings of tags: per-module and per-distr.
"""
if tag_name == ALL_PACKAGES_TAG:
builds, packages = self._get_release_packages()
else:
builds, packages = self._get_module_packages(tag_name)
return [
packages,
builds
]
def _get_release_packages(self):
"""
Search packages dir and keep only
packages that are non-modular.
This is quite the way how real koji works:
- modular packages are tagged by module-* tag
- all other packages are tagged with dist* tag
"""
packages = []
# get all rpms in folder
rpms = search_rpms(self._packages_dir)
all_rpms = [package.path for package in rpms]
# get nvras for modular packages
nvras = set()
for module in self._modules.values():
path = os.path.join(self._modules_dir, module.nvr)
info = Modulemd.ModuleStream.read_string(open(path).read(), strict=True)
for package in info.get_rpm_artifacts():
data = parse_nvra(package)
nvras.add((data['name'], data['version'], data['release'], data['arch']))
# and remove modular packages from global list
for rpm in all_rpms[:]:
data = parse_nvra(os.path.basename(rpm[:-4]))
if (data['name'], data['version'], data['release'], data['arch']) in nvras:
all_rpms.remove(rpm)
for rpm in all_rpms:
info = parse_nvra(os.path.basename(rpm))
packages.append({
"build_id": RELEASE_BUILD_ID,
"name": info['name'],
"extra": None,
"arch": info['arch'],
"epoch": info['epoch'] or None,
"version": info['version'],
"metadata_only": False,
"release": info['release'],
# not used currently
# "id": 262555,
# "size": 0
})
builds = []
return builds, packages
def _get_module_packages(self, tag_name):
"""
Get list of builds for module and given module tag name.
"""
path = os.path.join(self._modules_dir, tag_name)
module = self._get_module_by_name(tag_name)
builds = [
{
"build_id": module.build_id,
"package_name": module.name,
"nvr": module.nvr,
"tag_name": module.nvr,
"version": module.stream,
"release": module.version,
"id": module.build_id,
"name": module.name,
"volume_name": "DEFAULT",
# Following fields are currently not
# used but returned by real koji
# left them here just for reference
#
# "owner_name": "mbox-mbs-backend",
# "task_id": 195937,
# "state": 1,
# "start_time": "2020-12-22 19:20:12.504578",
# "creation_event_id": 306731,
# "creation_time": "2020-12-22 19:20:12.504578",
# "epoch": None,
# "tag_id": 1192,
# "completion_time": "2020-12-22 19:34:34.716615",
# "volume_id": 0,
# "package_id": 104,
# "owner_id": 6,
}
]
if module is None:
raise ValueError('Module %s is not found' % tag_name)
packages = []
if os.path.exists(path):
info = Modulemd.ModuleStream.read_string(open(path).read(), strict=True)
for art in info.get_rpm_artifacts():
data = parse_nvra(art)
packages.append({
"build_id": module.build_id,
"name": data['name'],
"extra": None,
"arch": data['arch'],
"epoch": data['epoch'] or None,
"version": data['version'],
"metadata_only": False,
"release": data['release'],
"id": 262555,
"size": 0
})
else:
raise RuntimeError('Unable to find module %s' % path)
return builds, packages
def _get_module_by_name(self, tag_name):
for module in self._modules.values():
if module.nvr != tag_name:
continue
return module
return None

View File

@ -26,6 +26,7 @@ import six
from six.moves import configparser, shlex_quote from six.moves import configparser, shlex_quote
import six.moves.xmlrpc_client as xmlrpclib import six.moves.xmlrpc_client as xmlrpclib
from .kojimock import KojiMock
from .. import util from .. import util
from ..arch_utils import getBaseArch from ..arch_utils import getBaseArch
@ -36,7 +37,7 @@ KOJI_BUILD_DELETED = koji.BUILD_STATES["DELETED"]
class KojiWrapper(object): class KojiWrapper(object):
lock = threading.Lock() lock = threading.Lock()
def __init__(self, profile): def __init__(self, profile, real_koji=False):
self.profile = profile self.profile = profile
with self.lock: with self.lock:
self.koji_module = koji.get_profile_module(profile) self.koji_module = koji.get_profile_module(profile)
@ -57,9 +58,14 @@ class KojiWrapper(object):
value = getattr(self.koji_module.config, key, None) value = getattr(self.koji_module.config, key, None)
if value is not None: if value is not None:
session_opts[key] = value session_opts[key] = value
self.koji_proxy = koji.ClientSession( if real_koji:
self.koji_module.config.server, session_opts self.koji_proxy = koji.ClientSession(
) self.koji_module.config.server, session_opts
)
else:
self.koji_proxy = KojiMock(
packages_dir=self.koji_module.config.topdir,
modules_dir=os.path.join(self.koji_module.config.topdir, 'modules'))
def login(self): def login(self):
"""Authenticate to the hub.""" """Authenticate to the hub."""

View File

@ -0,0 +1,356 @@
# -*- coding: utf-8 -*-
import os
import ddt
import unittest
from pyfakefs.fake_filesystem_unittest import TestCase
from pungi.wrappers.kojimock import KojiMock, RELEASE_BUILD_ID
PATH_TO_REPOS = '/path/to/repos'
MODULES_YAML_GZ = 'modules.yaml.gz'
@ddt.ddt
class TestLocalKojiMock(TestCase):
maxDiff = None
FILES_TO_CREATE = [
# modular package that should be excluded from global list
'powertools/Packages/ant-1.10.5-1.module_el8.0.0+30+832da3a1.noarch.rpm',
# packages that should be gathered
'powertools/Packages/libgit2-devel-0.26.8-2.el8.x86_64.rpm',
'appstream/Packages/OpenEXR-devel-2.2.0-11.el8.i686.rpm',
'appstream/Packages/mingw-binutils-generic-2.30-1.el8.x86_64.rpm',
# non-rpm
'appstream/Packages/somenonrpm',
]
MARIADB_MODULE = """
---
document: modulemd
version: 2
data:
name: mariadb-devel
stream: 10.3
version: 8010020200108182321
context: cdc1202b
arch: x86_64
summary: MariaDB Module
license:
content:
- (CDDL or GPLv2 with exceptions) and ASL 2.0
module:
- MIT
description: >-
MariaDB is a community developed branch of MySQL.
components:
rpms:
Judy:
rationale: MariaDB dependency for OQgraph computation engine
ref: a3583b33f939e74a530f2a1dff0552dff2c8ea73
buildorder: 4
arches: [aarch64, i686, ppc64le, x86_64]
artifacts:
rpms:
- Judy-0:1.0.5-18.module_el8.1.0+217+4d875839.i686
- Judy-debuginfo-0:1.0.5-18.module_el8.1.0+217+4d875839.i686
"""
JAVAPACKAGES_TOOLS_MODULE = """
---
document: modulemd
version: 2
data:
name: javapackages-tools
stream: 201801
version: 8000020190628172923
context: b07bea58
arch: x86_64
summary: Tools and macros for Java packaging support
license:
content:
- (CDDL or GPLv2 with exceptions) and ASL 2.0
module:
- MIT
description: >-
Java Packages Tools is a collection of tools that make it easier to build RPM
packages containing software running on Java platform.
components:
rpms:
ant:
rationale: "Runtime dependency of ant-contrib"
ref: 2eaf095676540e2805ee7e8c7f6f78285c428fdc
arches: [aarch64, i686, ppc64le, x86_64]
artifacts:
rpms:
- ant-0:1.10.5-1.module_el8.0.0+30+832da3a1.noarch
- ant-0:1.10.5-1.module_el8.0.0+30+832da3a1.src
"""
ANT_DEFAULTS = """
data:
module: ant
profiles:
'1.10':
- common
stream: '1.10'
document: modulemd-defaults
version: '1'
"""
def setUp(self):
self.setUpPyfakefs()
os.makedirs(PATH_TO_REPOS)
os.makedirs(os.path.join(PATH_TO_REPOS, 'modules'))
with open(os.path.join(PATH_TO_REPOS, 'modules',
'javapackages-tools-201801-8000020190628172923.b07bea58'), 'w') as f:
f.write(self.JAVAPACKAGES_TOOLS_MODULE)
with open(os.path.join(PATH_TO_REPOS, 'modules',
'mariadb-devel-10.3-8010020200108182321.cdc1202b'), 'w') as f:
f.write(self.MARIADB_MODULE)
for filepath in self.FILES_TO_CREATE:
os.makedirs(os.path.join(PATH_TO_REPOS, os.path.dirname(filepath)), exist_ok=True)
open(os.path.join(PATH_TO_REPOS, filepath), 'w').close()
self._koji = KojiMock(PATH_TO_REPOS, os.path.join(PATH_TO_REPOS, 'modules'))
@ddt.data(
[0, {
'completion_ts': 0,
'extra': {
'typeinfo': {
'module': {
'content_koji_tag': 'javapackages-tools-201801-8000020190628172923.b07bea58',
'context': 'b07bea58',
'name': 'javapackages-tools',
'stream': '201801',
'version': '8000020190628172923'
}
}
},
'id': 0,
'name': 'javapackages-tools',
'release': '8000020190628172923.b07bea58',
'state': 'COMPLETE',
'version': '201801'
}],
[1, {
'completion_ts': 0,
'extra': {
'typeinfo': {
'module': {
'content_koji_tag': 'mariadb-devel-10.3-8010020200108182321.cdc1202b',
'context': 'cdc1202b',
'name': 'mariadb-devel',
'stream': '10.3',
'version': '8010020200108182321'
}
}
},
'id': 1,
'name': 'mariadb-devel',
'release': '8010020200108182321.cdc1202b',
'state': 'COMPLETE',
'version': '10.3'
}]
)
@ddt.unpack
def test_get_build_info(self, build_id, result):
"""
Check that we are able to get build information from getBuild method
"""
build_info = self._koji.getBuild(build_id)
self.assertEqual(result, build_info)
@ddt.data(
[0, [{'btype': 'module', 'build_id': 0, 'filename': 'modulemd.x86_64.txt'},
{'btype': 'module', 'build_id': 0, 'filename': 'modulemd.txt'}]],
[1, [{'btype': 'module', 'build_id': 1, 'filename': 'modulemd.x86_64.txt'},
{'btype': 'module', 'build_id': 1, 'filename': 'modulemd.txt'}]]
)
@ddt.unpack
def test_list_archives(self, build_id, result):
"""
Provides list of archives of module descriptions.
Always should contain at least two files, so
I did a little hack and added modulemd.txt (it is on real koji)
but it is not used later by pungi
"""
build_info = self._koji.listArchives(build_id)
self.assertEqual(result, build_info)
@ddt.data(
[
'javapackages-tools-201801-8000020190628172923.b07bea58',
[
[
{
'arch': 'noarch',
'build_id': 0,
'epoch': '0',
'extra': None,
'id': 262555,
'metadata_only': False,
'name': 'ant',
'release': '1.module_el8.0.0+30+832da3a1',
'size': 0,
'version': '1.10.5'
},
{
'arch': 'src',
'build_id': 0,
'epoch': '0',
'extra': None,
'id': 262555,
'metadata_only': False,
'name': 'ant',
'release': '1.module_el8.0.0+30+832da3a1',
'size': 0,
'version': '1.10.5'
}
],
[
{
'build_id': 0,
'id': 0,
'name': 'javapackages-tools',
'nvr': 'javapackages-tools-201801-8000020190628172923.b07bea58',
'package_name': 'javapackages-tools',
'release': '8000020190628172923',
'tag_name': 'javapackages-tools-201801-8000020190628172923.b07bea58',
'version': '201801',
'volume_name': 'DEFAULT'
}
]
]
],
[
'mariadb-devel-10.3-8010020200108182321.cdc1202b',
[
[
{
'arch': 'i686',
'build_id': 1,
'epoch': '0',
'extra': None,
'id': 262555,
'metadata_only': False,
'name': 'Judy',
'release': '18.module_el8.1.0+217+4d875839',
'size': 0,
'version': '1.0.5'
},
{
'arch': 'i686',
'build_id': 1,
'epoch': '0',
'extra': None,
'id': 262555,
'metadata_only': False,
'name': 'Judy-debuginfo',
'release': '18.module_el8.1.0+217+4d875839',
'size': 0,
'version': '1.0.5'
}
],
[
{'build_id': 1,
'id': 1,
'name': 'mariadb-devel',
'nvr': 'mariadb-devel-10.3-8010020200108182321.cdc1202b',
'package_name': 'mariadb-devel',
'release': '8010020200108182321',
'tag_name': 'mariadb-devel-10.3-8010020200108182321.cdc1202b',
'version': '10.3',
'volume_name': 'DEFAULT'
}
]
]
],
[
'dist-c8-compose',
[
[
{
'arch': 'x86_64',
'build_id': RELEASE_BUILD_ID,
'epoch': None,
'extra': None,
'metadata_only': False,
'name': 'libgit2-devel',
'release': '2.el8',
'version': '0.26.8'
},
{
'arch': 'i686',
'build_id': RELEASE_BUILD_ID,
'epoch': None,
'extra': None,
'metadata_only': False,
'name': 'OpenEXR-devel',
'release': '11.el8',
'version': '2.2.0'
},
{
'arch': 'x86_64',
'build_id': RELEASE_BUILD_ID,
'epoch': None,
'extra': None,
'metadata_only': False,
'name': 'mingw-binutils-generic',
'release': '1.el8',
'version': '2.30'
}
],
# no build needed in this case because pungi does not use them
[]
]
],
)
@ddt.unpack
def test_list_tagged_rpms(self, tag, result):
"""
This method is used by pungi to get list of rpms:
either modular or just prepared for release
"""
self.assertEqual(result, self._koji.listTaggedRPMS(tag))
def test_list_tagged(self):
"""
Used only to get list of modules for some release.
"""
result = self._koji.listTagged('dist-c8-module-compose')
self.assertEqual([
{
'build_id': 0,
'id': 0,
'name': 'javapackages-tools',
'nvr': 'javapackages-tools-201801-8000020190628172923.b07bea58',
'owner_name': 'centos',
'package_name': 'javapackages-tools',
'release': '8000020190628172923.b07bea58',
'tag_name': 'dist-c8-module-compose',
'version': '201801'
},
{
'build_id': 1,
'id': 1,
'name': 'mariadb-devel',
'nvr': 'mariadb-devel-10.3-8010020200108182321.cdc1202b',
'owner_name': 'centos',
'package_name': 'mariadb-devel',
'release': '8010020200108182321.cdc1202b',
'tag_name': 'dist-c8-module-compose',
'version': '10.3'
}], result)
if __name__ == '__main__':
unittest.main()

View File

@ -49,7 +49,7 @@ class KojiWrapperBaseTestCase(unittest.TestCase):
) )
) )
self.koji_profile = koji.get_profile_module.return_value self.koji_profile = koji.get_profile_module.return_value
self.koji = KojiWrapper("custom-koji") self.koji = KojiWrapper("custom-koji", real_koji=True)
def tearDown(self): def tearDown(self):
os.remove(self.tmpfile) os.remove(self.tmpfile)

View File

@ -225,6 +225,7 @@ class TestKojiPkgset(PkgsetCompareMixin, helpers.PungiTestCase):
}, },
) )
@unittest.skip('Unneeded after lenix patch')
def test_find_signed_with_preference(self): def test_find_signed_with_preference(self):
self._touch_files( self._touch_files(
[ [
@ -255,6 +256,7 @@ class TestKojiPkgset(PkgsetCompareMixin, helpers.PungiTestCase):
}, },
) )
@unittest.skip('Unneeded after lenix patch')
def test_find_signed_fallback_unsigned(self): def test_find_signed_fallback_unsigned(self):
self._touch_files( self._touch_files(
[ [
@ -284,6 +286,7 @@ class TestKojiPkgset(PkgsetCompareMixin, helpers.PungiTestCase):
}, },
) )
@unittest.skip('Unneeded after lenix patch')
def test_can_not_find_signed_package(self): def test_can_not_find_signed_package(self):
pkgset = pkgsets.KojiPackageSet( pkgset = pkgsets.KojiPackageSet(
"pkgset", self.koji_wrapper, ["cafebabe"], arches=["x86_64"] "pkgset", self.koji_wrapper, ["cafebabe"], arches=["x86_64"]
@ -303,6 +306,7 @@ class TestKojiPkgset(PkgsetCompareMixin, helpers.PungiTestCase):
) )
self.assertRegex(str(ctx.exception), figure) self.assertRegex(str(ctx.exception), figure)
@unittest.skip('Unneeded after lenix patch')
def test_can_not_find_signed_package_allow_invalid_sigkeys(self): def test_can_not_find_signed_package_allow_invalid_sigkeys(self):
pkgset = pkgsets.KojiPackageSet( pkgset = pkgsets.KojiPackageSet(
"pkgset", "pkgset",
@ -328,6 +332,7 @@ class TestKojiPkgset(PkgsetCompareMixin, helpers.PungiTestCase):
) )
self.assertRegex(str(ctx.exception), figure) self.assertRegex(str(ctx.exception), figure)
@unittest.skip('Unneeded after lenix patch')
def test_can_not_find_any_package(self): def test_can_not_find_any_package(self):
pkgset = pkgsets.KojiPackageSet( pkgset = pkgsets.KojiPackageSet(
"pkgset", self.koji_wrapper, ["cafebabe", None], arches=["x86_64"] "pkgset", self.koji_wrapper, ["cafebabe", None], arches=["x86_64"]

View File

@ -683,6 +683,8 @@ class MockModule(object):
return self.path == other.path return self.path == other.path
# TODO: multiarch support was removed from modules
# and will be added by https://cloudlinux.atlassian.net/browse/LNX-108
@mock.patch("pungi.module_util.Modulemd.ModuleStream.read_file", new=MockModule) @mock.patch("pungi.module_util.Modulemd.ModuleStream.read_file", new=MockModule)
@unittest.skipIf(Modulemd is None, "Skipping tests, no module support") @unittest.skipIf(Modulemd is None, "Skipping tests, no module support")
class TestAddModuleToVariant(helpers.PungiTestCase): class TestAddModuleToVariant(helpers.PungiTestCase):
@ -690,6 +692,7 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
super(TestAddModuleToVariant, self).setUp() super(TestAddModuleToVariant, self).setUp()
self.koji = mock.Mock() self.koji = mock.Mock()
self.koji.koji_module.pathinfo.typedir.return_value = "/koji" self.koji.koji_module.pathinfo.typedir.return_value = "/koji"
self.koji.koji_module.pathinfo.topdir = "/mnt/koji"
files = ["modulemd.x86_64.txt", "modulemd.armv7hl.txt", "modulemd.txt"] files = ["modulemd.x86_64.txt", "modulemd.armv7hl.txt", "modulemd.txt"]
self.koji.koji_proxy.listArchives.return_value = [ self.koji.koji_proxy.listArchives.return_value = [
{"btype": "module", "filename": fname} for fname in files {"btype": "module", "filename": fname} for fname in files
@ -703,27 +706,31 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
"stream": "master", "stream": "master",
"version": "20190318", "version": "20190318",
"context": "abcdef", "context": "abcdef",
'content_koji_tag': 'module:master-20190318-abcdef'
}, },
}, },
}, },
} }
def test_adding_module(self): def test_adding_module(self):
variant = mock.Mock(arches=["armhfp", "x86_64"], arch_mmds={}, modules=[]) variant = mock.Mock(arches=[
# "armhfp",
"x86_64"
], arch_mmds={}, modules=[])
source_koji._add_module_to_variant(self.koji, variant, self.buildinfo) source_koji._add_module_to_variant(self.koji, variant, self.buildinfo)
self.assertEqual( self.assertEqual(
variant.arch_mmds, variant.arch_mmds,
{ {
"armhfp": { # "armhfp": {
"module:master:20190318:abcdef": MockModule( # "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.armv7hl.txt" # "/mnt/koji/modules/armv7hl/module:master-20190318-abcdef"
), # ),
}, # },
"x86_64": { "x86_64": {
"module:master:20190318:abcdef": MockModule( "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.x86_64.txt" "/mnt/koji/modules/module:master-20190318-abcdef"
), ),
}, },
}, },
@ -732,9 +739,12 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
def test_adding_module_to_existing(self): def test_adding_module_to_existing(self):
variant = mock.Mock( variant = mock.Mock(
arches=["armhfp", "x86_64"], arches=[
# "armhfp",
"x86_64"
],
arch_mmds={ arch_mmds={
"x86_64": {"m1:latest:20190101:cafe": MockModule("/koji/m1.x86_64.txt")} "x86_64": {"m1:latest:20190101:cafe": MockModule("/mnt/koji/modules/m1:latest:20190101:cafe")}
}, },
modules=[{"name": "m1:latest-20190101:cafe", "glob": False}], modules=[{"name": "m1:latest-20190101:cafe", "glob": False}],
) )
@ -744,16 +754,16 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
self.assertEqual( self.assertEqual(
variant.arch_mmds, variant.arch_mmds,
{ {
"armhfp": { # "armhfp": {
"module:master:20190318:abcdef": MockModule( # "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.armv7hl.txt" # "/mnt/koji/modules/armv7hl/module:master-20190318-abcdef"
), # ),
}, # },
"x86_64": { "x86_64": {
"module:master:20190318:abcdef": MockModule( "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.x86_64.txt" "/mnt/koji/modules/module:master-20190318-abcdef"
), ),
"m1:latest:20190101:cafe": MockModule("/koji/m1.x86_64.txt"), "m1:latest:20190101:cafe": MockModule("/mnt/koji/modules/m1:latest:20190101:cafe"),
}, },
}, },
) )
@ -762,7 +772,10 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
) )
def test_adding_module_with_add_module(self): def test_adding_module_with_add_module(self):
variant = mock.Mock(arches=["armhfp", "x86_64"], arch_mmds={}, modules=[]) variant = mock.Mock(arches=[
# "armhfp",
"x86_64"
], arch_mmds={}, modules=[])
source_koji._add_module_to_variant( source_koji._add_module_to_variant(
self.koji, variant, self.buildinfo, add_to_variant_modules=True self.koji, variant, self.buildinfo, add_to_variant_modules=True
@ -771,15 +784,15 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
self.assertEqual( self.assertEqual(
variant.arch_mmds, variant.arch_mmds,
{ {
"armhfp": { # "armhfp": {
"module:master:20190318:abcdef": MockModule( # "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.armv7hl.txt" # "/mnt/koji/modules/module:master-20190318-abcdef"
), # ),
}, # },
"x86_64": { "x86_64": {
"module:master:20190318:abcdef": MockModule( "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.x86_64.txt" "/mnt/koji/modules/module:master-20190318-abcdef"
), )
}, },
}, },
) )
@ -789,9 +802,12 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
def test_adding_module_to_existing_with_add_module(self): def test_adding_module_to_existing_with_add_module(self):
variant = mock.Mock( variant = mock.Mock(
arches=["armhfp", "x86_64"], arches=[
# "armhfp",
"x86_64"
],
arch_mmds={ arch_mmds={
"x86_64": {"m1:latest:20190101:cafe": MockModule("/koji/m1.x86_64.txt")} "x86_64": {"m1:latest:20190101:cafe": MockModule("/mnt/koji/modules/m1:latest:20190101:cafe")}
}, },
modules=[{"name": "m1:latest-20190101:cafe", "glob": False}], modules=[{"name": "m1:latest-20190101:cafe", "glob": False}],
) )
@ -803,16 +819,16 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
self.assertEqual( self.assertEqual(
variant.arch_mmds, variant.arch_mmds,
{ {
"armhfp": { # "armhfp": {
"module:master:20190318:abcdef": MockModule( # "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.armv7hl.txt" # "/koji/modulemd.armv7hl.txt"
), # ),
}, # },
"x86_64": { "x86_64": {
"module:master:20190318:abcdef": MockModule( "module:master:20190318:abcdef": MockModule(
"/koji/modulemd.x86_64.txt" "/mnt/koji/modules/module:master-20190318-abcdef"
), ),
"m1:latest:20190101:cafe": MockModule("/koji/m1.x86_64.txt"), "m1:latest:20190101:cafe": MockModule("/mnt/koji/modules/m1:latest:20190101:cafe"),
}, },
}, },
) )
@ -829,7 +845,10 @@ class TestAddModuleToVariant(helpers.PungiTestCase):
self.topdir, {"filter_modules": [(".*", {"*": ["module:*"]})]} self.topdir, {"filter_modules": [(".*", {"*": ["module:*"]})]}
) )
variant = mock.Mock( variant = mock.Mock(
arches=["armhfp", "x86_64"], arch_mmds={}, modules=[], uid="Variant" arches=[
# "armhfp",
"x86_64"
], arch_mmds={}, modules=[], uid="Variant"
) )
nsvc = source_koji._add_module_to_variant( nsvc = source_koji._add_module_to_variant(
@ -914,7 +933,10 @@ class TestAddScratchModuleToVariant(helpers.PungiTestCase):
) )
def test_adding_scratch_module(self, mock_mmd): def test_adding_scratch_module(self, mock_mmd):
variant = mock.Mock( variant = mock.Mock(
arches=["armhfp", "x86_64"], arches=[
# "armhfp",
"x86_64"
],
arch_mmds={}, arch_mmds={},
modules=[], modules=[],
module_uid_to_koji_tag={}, module_uid_to_koji_tag={},