Skip to content

Commit

Permalink
sanity_check_repo() now supports modular repositories.
Browse files Browse the repository at this point in the history
There was a crash in sanity_check_repo() as it expected to find
elements that were not present. This commit adjusts it to look for
the appropriate elements for modular repositories.

fixes #2631

Signed-off-by: Randy Barlow <randy@electronsweatshop.com>
(cherry picked from commit d964341)
  • Loading branch information
bowlofeggs committed Oct 9, 2018
1 parent e22db12 commit 952a043
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 17 deletions.
5 changes: 3 additions & 2 deletions bodhi/server/consumers/masher.py
Original file line number Diff line number Diff line change
Expand Up @@ -1148,11 +1148,12 @@ def _sanity_check_repo(self):
if arch == 'source':
repodata = os.path.join(self.path, 'compose',
'Everything', arch, 'tree', 'repodata')
sanity_check_repodata(repodata, source=True)
sanity_check_repodata(repodata, repo_type='source')
else:
repodata = os.path.join(self.path, 'compose',
'Everything', arch, 'os', 'repodata')
sanity_check_repodata(repodata, source=False)
repo_type = 'module' if self.ctype == ContentType.module else 'yum'
sanity_check_repodata(repodata, repo_type=repo_type)
except Exception:
self.log.exception("Repodata sanity check failed, compose thrown out")
self._toss_out_repo()
Expand Down
19 changes: 13 additions & 6 deletions bodhi/server/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,21 @@ def get_critpath_components(collection='master', component_type='rpm', component
return critpath_components


def sanity_check_repodata(myurl, source):
def sanity_check_repodata(myurl, repo_type):
"""
Sanity check the repodata for a given repository.
Args:
myurl (basestring): A path to a repodata directory.
source (bool): True if we are checking a source RPM repository, False otherwise.
repo_type (str): This should be set to 'yum' for Yum repositories, 'module' for module
repositories, or 'source' for source repositories.
Raises:
Exception: If the repodata is not valid or does not exist.
ValueError: If repo_type is not an acceptable value.
"""
if repo_type not in ('module', 'source', 'yum'):
raise ValueError('repo_type must be one of module, source, or yum.')

h = librepo.Handle()
h.setopt(librepo.LRO_REPOTYPE, librepo.LR_YUMREPO)
h.setopt(librepo.LRO_DESTDIR, tempfile.mkdtemp())
Expand All @@ -280,9 +285,11 @@ def sanity_check_repodata(myurl, source):
hk_repo = hawkey.Repo(myurl)
try:
hk_repo.filelists_fn = repo_info['filelists']
# Source repos don't have DRPMs.
if not source:
# Source and module repos don't have DRPMs.
if repo_type == 'yum':
hk_repo.presto_fn = repo_info['prestodelta']
elif repo_type == 'module':
hk_repo.presto_fn = repo_info['modules']
hk_repo.primary_fn = repo_info['primary']
hk_repo.repomd_fn = repo_info['repomd']
hk_repo.updateinfo_fn = repo_info['updateinfo']
Expand All @@ -294,8 +301,8 @@ def sanity_check_repodata(myurl, source):
load_presto=True,
load_updateinfo=True)

# Source repos don't have comps.
if not source:
# Only yum repos have comps
if repo_type == 'yum':
# Test comps
comps = libcomps.Comps()
try:
Expand Down
32 changes: 25 additions & 7 deletions bodhi/tests/server/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,12 +535,30 @@ def setUp(self):
def tearDown(self):
shutil.rmtree(self.tempdir)

def test_correct_repo(self):
def test_correct_yum_repo(self):
"""No Exception should be raised if the repo is normal."""
base.mkmetadatadir(self.tempdir)

# No exception should be raised here.
util.sanity_check_repodata(self.tempdir, source=False)
util.sanity_check_repodata(self.tempdir, repo_type='yum')

def test_correct_module_repo(self):
"""No Exception should be raised if the repo is a normal module repo."""
base.mkmetadatadir(self.tempdir)
# We need to add a modules tag to repomd.
repomd_path = os.path.join(self.tempdir, 'repodata', 'repomd.xml')
repomd_tree = ElementTree.parse(repomd_path)
ElementTree.register_namespace('', 'http://linux.duke.edu/metadata/repo')
root = repomd_tree.getroot()
ElementTree.SubElement(root, 'data', type='modules')
for data in root.findall('{http://linux.duke.edu/metadata/repo}data'):
# module repos don't have drpms or comps.
if data.attrib['type'] in ('group', 'prestodelta'):
root.remove(data)
repomd_tree.write(repomd_path, encoding='UTF-8', xml_declaration=True)

# No exception should be raised here.
util.sanity_check_repodata(self.tempdir, repo_type='module')

def test_updateinfo_empty_tags(self):
"""RepodataException should be raised if <id/> is found in updateinfo."""
Expand All @@ -550,7 +568,7 @@ def test_updateinfo_empty_tags(self):
base.mkmetadatadir(self.tempdir, updateinfo=updateinfo)

with self.assertRaises(util.RepodataException) as exc:
util.sanity_check_repodata(self.tempdir, source=False)
util.sanity_check_repodata(self.tempdir, repo_type='yum')

self.assertEqual(str(exc.exception), 'updateinfo.xml.gz contains empty ID tags')

Expand All @@ -562,7 +580,7 @@ def test_comps_invalid_notxml(self):
base.mkmetadatadir(self.tempdir, comps=comps)

with self.assertRaises(util.RepodataException) as exc:
util.sanity_check_repodata(self.tempdir, source=False)
util.sanity_check_repodata(self.tempdir, repo_type='yum')

self.assertEqual(str(exc.exception), 'Comps file unable to be parsed')

Expand All @@ -574,7 +592,7 @@ def test_comps_invalid_nonsense(self):
base.mkmetadatadir(self.tempdir, comps=comps)

with self.assertRaises(util.RepodataException) as exc:
util.sanity_check_repodata(self.tempdir, source=False)
util.sanity_check_repodata(self.tempdir, repo_type='yum')

self.assertEqual(str(exc.exception), 'Comps file empty')

Expand All @@ -592,7 +610,7 @@ def test_repomd_missing_updateinfo(self):
repomd.write(repomd_path, encoding='UTF-8', xml_declaration=True)

with self.assertRaises(util.RepodataException) as exc:
util.sanity_check_repodata(self.tempdir, source=False)
util.sanity_check_repodata(self.tempdir, repo_type='yum')

self.assertEqual(str(exc.exception), 'Required part not in repomd.xml')

Expand All @@ -610,7 +628,7 @@ def test_source_true(self):
repomd.write(repomd_path, encoding='UTF-8', xml_declaration=True)

# No exception should be raised.
util.sanity_check_repodata(self.tempdir, source=True)
util.sanity_check_repodata(self.tempdir, repo_type='source')


class TestType2Icon(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
# The short X.Y version.
version = '3.10'
# The full version, including alpha/beta/rc tags.
release = '3.10.0'
release = '3.10.1'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
6 changes: 6 additions & 0 deletions docs/user/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Release notes
=============

v3.10.1
-------

This releases fixes a crash while composing modular repositories (:issue:`2631`).


v3.10.0
-------

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def get_requirements(requirements_file='requirements.txt'):

here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.rst')).read()
VERSION = '3.10.0'
VERSION = '3.10.1'
# Possible options are at https://pypi.python.org/pypi?%3Aaction=list_classifiers
CLASSIFIERS = [
'Development Status :: 5 - Production/Stable',
Expand Down

0 comments on commit 952a043

Please sign in to comment.