Merge #339 Refactor failables, step 1
This commit is contained in:
commit
247149d4e1
@ -117,13 +117,6 @@ Example
|
||||
base_product_short = "Fedora"
|
||||
base_product_version = "23"
|
||||
|
||||
**tree_arches**
|
||||
([*str*]) -- list of architectures which should be included; if undefined, all architectures from variants.xml will be included
|
||||
|
||||
**tree_variants**
|
||||
([*str*]) -- list of variants which should be included; if undefined, all variants from variants.xml will be included
|
||||
|
||||
|
||||
General Settings
|
||||
================
|
||||
|
||||
@ -138,28 +131,12 @@ Options
|
||||
|
||||
**failable_deliverables** [optional]
|
||||
(*list*) -- list which deliverables on which variant and architecture can
|
||||
fail and not abort the whole compose
|
||||
|
||||
Currently handled deliverables are:
|
||||
* buildinstall
|
||||
* iso
|
||||
* live
|
||||
* image-build
|
||||
* live-media
|
||||
* ostree
|
||||
* ostree-installer
|
||||
* osbs
|
||||
|
||||
.. note::
|
||||
|
||||
Image building is not run per-architecture. If you want to mark it
|
||||
as failable, specify it in a block with arch set as ``*``.
|
||||
fail and not abort the whole compose. This only applies to ``buildinstall``
|
||||
and ``iso`` parts. All other artifacts can be configured in their
|
||||
respective part of configuration.
|
||||
|
||||
Please note that ``*`` as a wildcard matches all architectures but ``src``.
|
||||
|
||||
tree_arches = ["x86_64"]
|
||||
tree_variants = ["Server"]
|
||||
|
||||
**comps_filter_environments** [optional]
|
||||
(*bool*) -- When set to ``False``, the comps files for variants will not
|
||||
have their environments filtered to match the variant.
|
||||
@ -168,6 +145,15 @@ Options
|
||||
(*list*) -- List of variants for which the original comps file will be
|
||||
copied without any modifications. Overwrites `comps_filter_environments`.
|
||||
|
||||
**tree_arches**
|
||||
([*str*]) -- list of architectures which should be included; if undefined,
|
||||
all architectures from variants.xml will be included
|
||||
|
||||
**tree_variants**
|
||||
([*str*]) -- list of variants which should be included; if undefined, all
|
||||
variants from variants.xml will be included
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
::
|
||||
@ -196,6 +182,9 @@ Example
|
||||
})
|
||||
]
|
||||
|
||||
tree_arches = ["x86_64"]
|
||||
tree_variants = ["Server"]
|
||||
|
||||
|
||||
Image Naming
|
||||
============
|
||||
@ -836,6 +825,14 @@ will be generated based on date, compose type and respin.
|
||||
* ``image_build_release``
|
||||
* ``live_images_release``
|
||||
|
||||
Each configuration block can also optionally specify a list of architectures
|
||||
that are not release blocking with ``failable`` key. If any deliverable fails,
|
||||
it will not abort the whole compose. Due to limitations in how the tasks are
|
||||
done in Koji, if any architecture fails, all of them fail. Until this is
|
||||
resolved, it is not possible to configure failability per architecture. An
|
||||
empty list means required deliverable, non-empty list means non-blocking
|
||||
deliverable.
|
||||
|
||||
|
||||
Live Images Settings
|
||||
====================
|
||||
@ -1059,6 +1056,8 @@ runroot environment.
|
||||
|
||||
* ``config_branch`` -- (*str*) Git branch of the repo to use. Defaults to
|
||||
``master``.
|
||||
* ``failable`` -- (*[str]*) List of architectures for which this
|
||||
deliverable is not release blocking.
|
||||
|
||||
|
||||
Example config
|
||||
@ -1096,6 +1095,8 @@ an OSTree repository. This always runs in Koji as a ``runroot`` task.
|
||||
|
||||
* ``release`` -- (*str*) Release value to set for the installer image. Set
|
||||
to ``None`` to use the date.respin format.
|
||||
* ``failable`` -- (*[str]*) List of architectures for which this
|
||||
deliverable is not release blocking.
|
||||
|
||||
These optional keys are passed to ``lorax`` to customize the build.
|
||||
|
||||
@ -1163,6 +1164,14 @@ they are not scratch builds).
|
||||
Please see :ref:`git-urls` section for more details.
|
||||
* ``target`` -- (*str*) A Koji target to build the image for.
|
||||
|
||||
Optionally you can specify ``failable``. If it has a truthy value, failure
|
||||
to create the image will not abort the whole compose.
|
||||
|
||||
.. note::
|
||||
Once OSBS gains support for multiple architectures, the usage of this
|
||||
option will most likely change to list architectures that are allowed
|
||||
to fail.
|
||||
|
||||
The configuration will pass other attributes directly to the Koji task.
|
||||
This includes ``name``, ``version``, ``scratch`` and ``priority``.
|
||||
|
||||
|
@ -190,9 +190,10 @@ class BuildinstallPhase(PhaseBase):
|
||||
# TODO: label is not used
|
||||
label = ""
|
||||
volid = get_volid(self.compose, arch, variant, escape_spaces=False, disc_type=disc_type)
|
||||
with failable(self.compose, variant, arch, 'buildinstall'):
|
||||
can_fail = self.compose.can_fail(variant, arch, 'buildinstall')
|
||||
with failable(self.compose, can_fail, variant, arch, 'buildinstall'):
|
||||
tweak_buildinstall(buildinstall_dir, os_tree, arch, variant.uid, label, volid, kickstart_file)
|
||||
link_boot_iso(self.compose, arch, variant)
|
||||
link_boot_iso(self.compose, arch, variant, can_fail)
|
||||
|
||||
|
||||
def get_kickstart_file(compose):
|
||||
@ -315,7 +316,7 @@ def tweak_buildinstall(src, dst, arch, variant, label, volid, kickstart_file=Non
|
||||
shutil.rmtree(tmp_dir)
|
||||
|
||||
|
||||
def link_boot_iso(compose, arch, variant):
|
||||
def link_boot_iso(compose, arch, variant, can_fail):
|
||||
if arch == "src":
|
||||
return
|
||||
|
||||
@ -369,6 +370,7 @@ def link_boot_iso(compose, arch, variant):
|
||||
img.bootable = True
|
||||
img.subvariant = variant.name
|
||||
img.implant_md5 = implant_md5
|
||||
setattr(img, 'can_fail', can_fail)
|
||||
setattr(img, 'deliverable', 'buildinstall')
|
||||
try:
|
||||
img.volume_id = iso.get_volume_id(new_boot_iso_path)
|
||||
@ -382,7 +384,8 @@ class BuildinstallThread(WorkerThread):
|
||||
def process(self, item, num):
|
||||
# The variant is None unless lorax is used as buildinstall method.
|
||||
compose, arch, variant, cmd = item
|
||||
with failable(compose, variant, arch, 'buildinstall'):
|
||||
can_fail = compose.can_fail(variant, arch, 'buildinstall')
|
||||
with failable(compose, can_fail, variant, arch, 'buildinstall'):
|
||||
self.worker(compose, arch, variant, cmd, num)
|
||||
|
||||
def worker(self, compose, arch, variant, cmd, num):
|
||||
|
@ -183,7 +183,8 @@ class CreateIsoThread(WorkerThread):
|
||||
|
||||
def process(self, item, num):
|
||||
compose, cmd, variant, arch = item
|
||||
with failable(compose, variant, arch, 'iso'):
|
||||
can_fail = compose.can_fail(variant, arch, 'iso')
|
||||
with failable(compose, can_fail, variant, arch, 'iso'):
|
||||
self.worker(compose, cmd, variant, arch, num)
|
||||
|
||||
def worker(self, compose, cmd, variant, arch, num):
|
||||
|
@ -157,6 +157,7 @@ class ImageBuildPhase(base.ImageConfigMixin, base.ConfigGuardedPhase):
|
||||
),
|
||||
"link_type": self.compose.conf.get("link_type", "hardlink-or-copy"),
|
||||
"scratch": image_conf['image-build'].pop('scratch', False),
|
||||
"failable_arches": image_conf.pop('failable', []),
|
||||
}
|
||||
self.pool.add(CreateImageBuildThread(self.pool))
|
||||
self.pool.queue_put((self.compose, cmd))
|
||||
@ -172,7 +173,10 @@ class CreateImageBuildThread(WorkerThread):
|
||||
compose, cmd = item
|
||||
variant = cmd["image_conf"]["image-build"]["variant"]
|
||||
subvariant = cmd["image_conf"]["image-build"].get("subvariant", variant.uid)
|
||||
with failable(compose, variant, '*', 'image-build', subvariant):
|
||||
failable_arches = cmd.get('failable_arches', [])
|
||||
self.can_fail = bool(failable_arches)
|
||||
# TODO handle failure per architecture; currently not possible in single task
|
||||
with failable(compose, self.can_fail, variant, '*', 'image-build', subvariant):
|
||||
self.worker(num, compose, variant, subvariant, cmd)
|
||||
|
||||
def worker(self, num, compose, variant, subvariant, cmd):
|
||||
@ -253,6 +257,7 @@ class CreateImageBuildThread(WorkerThread):
|
||||
img.disc_count = 1
|
||||
img.bootable = False
|
||||
img.subvariant = subvariant
|
||||
setattr(img, 'can_fail', self.can_fail)
|
||||
setattr(img, 'deliverable', 'image-build')
|
||||
compose.im.add(variant=variant.uid, arch=image_info['arch'], image=img)
|
||||
|
||||
|
@ -157,6 +157,7 @@ class LiveImagesPhase(base.ImageConfigMixin, base.ConfigGuardedPhase):
|
||||
"type": type,
|
||||
"label": "", # currently not used
|
||||
"subvariant": subvariant,
|
||||
"failable_arches": data.get('failable', []),
|
||||
}
|
||||
|
||||
cmd["repos"] = self._get_repos(arch, variant, data)
|
||||
@ -199,7 +200,10 @@ class CreateLiveImageThread(WorkerThread):
|
||||
|
||||
def process(self, item, num):
|
||||
compose, cmd, variant, arch = item
|
||||
with failable(compose, variant, arch, 'live', cmd.get('subvariant')):
|
||||
self.failable_arches = cmd.get('failable_arches', [])
|
||||
# TODO handle failure per architecture; currently not possible in single task
|
||||
self.can_fail = bool(self.failable_arches)
|
||||
with failable(compose, self.can_fail, variant, arch, 'live', cmd.get('subvariant')):
|
||||
self.worker(compose, cmd, variant, arch, num)
|
||||
|
||||
def worker(self, compose, cmd, variant, arch, num):
|
||||
@ -290,6 +294,7 @@ class CreateLiveImageThread(WorkerThread):
|
||||
img.disc_count = 1
|
||||
img.bootable = True
|
||||
img.subvariant = subvariant
|
||||
setattr(img, 'can_fail', self.can_fail)
|
||||
setattr(img, 'deliverable', 'live')
|
||||
compose.im.add(variant=variant.uid, arch=arch, image=img)
|
||||
|
||||
|
@ -116,6 +116,7 @@ class LiveMediaPhase(ImageConfigMixin, ConfigGuardedPhase):
|
||||
'repo': self._get_repos(image_conf, variant),
|
||||
'install_tree': self._get_install_tree(image_conf, variant),
|
||||
'version': self.get_config(image_conf, 'version'),
|
||||
'failable_arches': image_conf.get('failable', []),
|
||||
}
|
||||
self.pool.add(LiveMediaThread(self.pool))
|
||||
self.pool.queue_put((self.compose, variant, config))
|
||||
@ -127,8 +128,10 @@ class LiveMediaThread(WorkerThread):
|
||||
def process(self, item, num):
|
||||
compose, variant, config = item
|
||||
subvariant = config.pop('subvariant')
|
||||
self.failable_arches = config.pop('failable_arches')
|
||||
self.num = num
|
||||
with failable(compose, variant, '*', 'live-media', subvariant):
|
||||
# TODO handle failure per architecture; currently not possible in single task
|
||||
with failable(compose, bool(self.failable_arches), variant, '*', 'live-media', subvariant):
|
||||
self.worker(compose, variant, subvariant, config)
|
||||
|
||||
def _get_log_file(self, compose, variant, subvariant, config):
|
||||
@ -204,6 +207,7 @@ class LiveMediaThread(WorkerThread):
|
||||
img.disc_count = 1
|
||||
img.bootable = True
|
||||
img.subvariant = subvariant
|
||||
setattr(img, 'can_fail', bool(self.failable_arches))
|
||||
setattr(img, 'deliverable', 'live-media')
|
||||
compose.im.add(variant=variant.uid, arch=image_info['arch'], image=img)
|
||||
|
||||
|
@ -47,7 +47,7 @@ class OSBSThread(WorkerThread):
|
||||
def process(self, item, num):
|
||||
compose, variant, config = item
|
||||
self.num = num
|
||||
with util.failable(compose, variant, '*', 'osbs'):
|
||||
with util.failable(compose, bool(config.pop('failable', None)), variant, '*', 'osbs'):
|
||||
self.worker(compose, variant, config)
|
||||
|
||||
def worker(self, compose, variant, config):
|
||||
|
@ -39,7 +39,9 @@ class OSTreeThread(WorkerThread):
|
||||
def process(self, item, num):
|
||||
compose, variant, arch, config = item
|
||||
self.num = num
|
||||
with util.failable(compose, variant, arch, 'ostree'):
|
||||
failable_arches = config.get('failable', [])
|
||||
with util.failable(compose, util.can_arch_fail(failable_arches, arch),
|
||||
variant, arch, 'ostree'):
|
||||
self.worker(compose, variant, arch, config)
|
||||
|
||||
def worker(self, compose, variant, arch, config):
|
||||
|
@ -42,7 +42,9 @@ class OstreeInstallerThread(WorkerThread):
|
||||
def process(self, item, num):
|
||||
compose, variant, arch, config = item
|
||||
self.num = num
|
||||
with util.failable(compose, variant, arch, 'ostree-installer'):
|
||||
failable_arches = config.get('failable', [])
|
||||
self.can_fail = util.can_arch_fail(failable_arches, arch)
|
||||
with util.failable(compose, self.can_fail, variant, arch, 'ostree-installer'):
|
||||
self.worker(compose, variant, arch, config)
|
||||
|
||||
def worker(self, compose, variant, arch, config):
|
||||
@ -119,6 +121,7 @@ class OstreeInstallerThread(WorkerThread):
|
||||
img.bootable = True
|
||||
img.subvariant = variant.name
|
||||
img.implant_md5 = implant_md5
|
||||
setattr(img, 'can_fail', self.can_fail)
|
||||
setattr(img, 'deliverable', 'ostree-installer')
|
||||
try:
|
||||
img.volume_id = iso_wrapper.get_volume_id(full_iso_path)
|
||||
|
@ -125,7 +125,9 @@ def check(compose, variant, arch, image):
|
||||
result = True
|
||||
path = os.path.join(compose.paths.compose.topdir(), image.path)
|
||||
deliverable = getattr(image, 'deliverable')
|
||||
with failable(compose, variant, arch, deliverable, subvariant=image.subvariant):
|
||||
can_fail = getattr(image, 'can_fail', False)
|
||||
with failable(compose, can_fail, variant, arch, deliverable,
|
||||
subvariant=image.subvariant):
|
||||
with open(path) as f:
|
||||
iso = is_iso(f)
|
||||
if image.format == 'iso' and not iso:
|
||||
|
@ -464,10 +464,9 @@ def process_args(fmt, args):
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def failable(compose, variant, arch, deliverable, subvariant=None):
|
||||
def failable(compose, can_fail, variant, arch, deliverable, subvariant=None):
|
||||
"""If a deliverable can fail, log a message and go on as if it succeeded."""
|
||||
msg = deliverable.replace('-', ' ').capitalize()
|
||||
can_fail = compose.can_fail(variant, arch, deliverable)
|
||||
if can_fail:
|
||||
compose.attempt_deliverable(variant, arch, deliverable, subvariant)
|
||||
else:
|
||||
@ -489,6 +488,11 @@ def failable(compose, variant, arch, deliverable, subvariant=None):
|
||||
compose.log_debug(tb)
|
||||
|
||||
|
||||
def can_arch_fail(failable_arches, arch):
|
||||
"""Check if `arch` is in `failable_arches` or `*` can fail."""
|
||||
return '*' in failable_arches or arch in failable_arches
|
||||
|
||||
|
||||
def get_format_substs(compose, **kwargs):
|
||||
"""Return a dict of basic format substitutions.
|
||||
|
||||
|
@ -62,7 +62,7 @@ class DummyCompose(object):
|
||||
self.log_debug = mock.Mock()
|
||||
self.log_warning = mock.Mock()
|
||||
self.get_image_name = mock.Mock(return_value='image-name')
|
||||
self.image = mock.Mock(path='Client/i386/iso/image.iso')
|
||||
self.image = mock.Mock(path='Client/i386/iso/image.iso', can_fail=False)
|
||||
self.im = mock.Mock(images={'Client': {'amd64': [self.image]}})
|
||||
self.old_composes = []
|
||||
self.config_dir = '/home/releng/config'
|
||||
|
@ -355,9 +355,9 @@ class TestCopyFiles(PungiTestCase):
|
||||
'amd64', 'Client', '', 'Client.amd64', 'kickstart')])
|
||||
self.assertItemsEqual(
|
||||
link_boot_iso.mock_calls,
|
||||
[mock.call(compose, 'x86_64', compose.variants['Server']),
|
||||
mock.call(compose, 'amd64', compose.variants['Client']),
|
||||
mock.call(compose, 'amd64', compose.variants['Server'])])
|
||||
[mock.call(compose, 'x86_64', compose.variants['Server'], False),
|
||||
mock.call(compose, 'amd64', compose.variants['Client'], False),
|
||||
mock.call(compose, 'amd64', compose.variants['Server'], False)])
|
||||
|
||||
@mock.patch('pungi.phases.buildinstall.link_boot_iso')
|
||||
@mock.patch('pungi.phases.buildinstall.tweak_buildinstall')
|
||||
@ -397,9 +397,9 @@ class TestCopyFiles(PungiTestCase):
|
||||
'amd64', 'Client', '', 'Client.amd64', 'kickstart')])
|
||||
self.assertItemsEqual(
|
||||
link_boot_iso.mock_calls,
|
||||
[mock.call(compose, 'x86_64', compose.variants['Server']),
|
||||
mock.call(compose, 'amd64', compose.variants['Client']),
|
||||
mock.call(compose, 'amd64', compose.variants['Server'])])
|
||||
[mock.call(compose, 'x86_64', compose.variants['Server'], False),
|
||||
mock.call(compose, 'amd64', compose.variants['Client'], False),
|
||||
mock.call(compose, 'amd64', compose.variants['Server'], False)])
|
||||
|
||||
@mock.patch('pungi.phases.buildinstall.link_boot_iso')
|
||||
@mock.patch('pungi.phases.buildinstall.tweak_buildinstall')
|
||||
@ -622,7 +622,7 @@ class TestSymlinkIso(PungiTestCase):
|
||||
get_file_size.return_value = 1024
|
||||
get_mtime.return_value = 13579
|
||||
|
||||
link_boot_iso(self.compose, 'x86_64', self.compose.variants['Server'])
|
||||
link_boot_iso(self.compose, 'x86_64', self.compose.variants['Server'], False)
|
||||
|
||||
tgt = self.topdir + '/compose/Server/x86_64/iso/image-name'
|
||||
self.assertTrue(os.path.isfile(tgt))
|
||||
@ -654,6 +654,7 @@ class TestSymlinkIso(PungiTestCase):
|
||||
self.assertEqual(image.disc_count, 1)
|
||||
self.assertEqual(image.bootable, True)
|
||||
self.assertEqual(image.implant_md5, IsoWrapper.get_implanted_md5.return_value)
|
||||
self.assertEqual(image.can_fail, False)
|
||||
self.assertEqual(self.compose.im.add.mock_calls,
|
||||
[mock.call('Server', 'x86_64', image)])
|
||||
|
||||
@ -671,7 +672,7 @@ class TestSymlinkIso(PungiTestCase):
|
||||
get_file_size.return_value = 1024
|
||||
get_mtime.return_value = 13579
|
||||
|
||||
link_boot_iso(self.compose, 'x86_64', self.compose.variants['Server'])
|
||||
link_boot_iso(self.compose, 'x86_64', self.compose.variants['Server'], True)
|
||||
|
||||
tgt = self.topdir + '/compose/Server/x86_64/iso/image-name'
|
||||
self.assertTrue(os.path.isfile(tgt))
|
||||
@ -703,6 +704,7 @@ class TestSymlinkIso(PungiTestCase):
|
||||
self.assertEqual(image.disc_count, 1)
|
||||
self.assertEqual(image.bootable, True)
|
||||
self.assertEqual(image.implant_md5, IsoWrapper.get_implanted_md5.return_value)
|
||||
self.assertEqual(image.can_fail, True)
|
||||
self.assertEqual(self.compose.im.add.mock_calls,
|
||||
[mock.call('Server', 'x86_64', image)])
|
||||
|
||||
|
@ -71,6 +71,7 @@ class TestImageBuildPhase(PungiTestCase):
|
||||
"relative_image_dir": 'Client/%(arch)s/images',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
"scratch": False,
|
||||
"failable_arches": [],
|
||||
}
|
||||
server_args = {
|
||||
"format": [('docker', 'tar.xz')],
|
||||
@ -95,6 +96,7 @@ class TestImageBuildPhase(PungiTestCase):
|
||||
"relative_image_dir": 'Server/%(arch)s/images',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
"scratch": False,
|
||||
"failable_arches": [],
|
||||
}
|
||||
self.maxDiff = None
|
||||
self.assertItemsEqual(phase.pool.queue_put.mock_calls,
|
||||
@ -155,6 +157,7 @@ class TestImageBuildPhase(PungiTestCase):
|
||||
"relative_image_dir": 'Server/%(arch)s/images',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
"scratch": False,
|
||||
"failable_arches": [],
|
||||
}
|
||||
self.maxDiff = None
|
||||
self.assertItemsEqual(phase.pool.queue_put.mock_calls,
|
||||
@ -249,6 +252,7 @@ class TestImageBuildPhase(PungiTestCase):
|
||||
"relative_image_dir": 'Server/%(arch)s/images',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
"scratch": False,
|
||||
"failable_arches": [],
|
||||
})
|
||||
|
||||
@mock.patch('pungi.phases.image_build.ThreadPool')
|
||||
@ -310,6 +314,7 @@ class TestImageBuildPhase(PungiTestCase):
|
||||
"relative_image_dir": 'Server/%(arch)s/images',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
"scratch": False,
|
||||
"failable_arches": [],
|
||||
})
|
||||
|
||||
@mock.patch('pungi.phases.image_build.ThreadPool')
|
||||
@ -370,6 +375,7 @@ class TestImageBuildPhase(PungiTestCase):
|
||||
"relative_image_dir": 'Server/%(arch)s/images',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
"scratch": False,
|
||||
"failable_arches": [],
|
||||
})
|
||||
|
||||
@mock.patch('pungi.phases.image_build.ThreadPool')
|
||||
@ -621,14 +627,7 @@ class TestCreateImageBuildThread(PungiTestCase):
|
||||
@mock.patch('pungi.phases.image_build.KojiWrapper')
|
||||
@mock.patch('pungi.phases.image_build.Linker')
|
||||
def test_process_handle_fail(self, Linker, KojiWrapper):
|
||||
compose = DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'failable_deliverables': [
|
||||
('^.*$', {
|
||||
'*': ['image-build']
|
||||
})
|
||||
]
|
||||
})
|
||||
compose = DummyCompose(self.topdir, {'koji_profile': 'koji'})
|
||||
pool = mock.Mock()
|
||||
cmd = {
|
||||
"format": [('docker', 'tar.xz'), ('qcow2', 'qcow2')],
|
||||
@ -653,6 +652,7 @@ class TestCreateImageBuildThread(PungiTestCase):
|
||||
"relative_image_dir": 'image_dir/Client/%(arch)s',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
'scratch': False,
|
||||
"failable_arches": ['*'],
|
||||
}
|
||||
koji_wrapper = KojiWrapper.return_value
|
||||
koji_wrapper.run_blocking_cmd.return_value = {
|
||||
@ -675,14 +675,7 @@ class TestCreateImageBuildThread(PungiTestCase):
|
||||
@mock.patch('pungi.phases.image_build.KojiWrapper')
|
||||
@mock.patch('pungi.phases.image_build.Linker')
|
||||
def test_process_handle_exception(self, Linker, KojiWrapper):
|
||||
compose = DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'failable_deliverables': [
|
||||
('^.*$', {
|
||||
'*': ['image-build']
|
||||
})
|
||||
]
|
||||
})
|
||||
compose = DummyCompose(self.topdir, {'koji_profile': 'koji'})
|
||||
pool = mock.Mock()
|
||||
cmd = {
|
||||
"format": [('docker', 'tar.xz'), ('qcow2', 'qcow2')],
|
||||
@ -707,6 +700,7 @@ class TestCreateImageBuildThread(PungiTestCase):
|
||||
"relative_image_dir": 'image_dir/Client/%(arch)s',
|
||||
"link_type": 'hardlink-or-copy',
|
||||
'scratch': False,
|
||||
"failable_arches": ['*'],
|
||||
}
|
||||
|
||||
koji_wrapper = KojiWrapper.return_value
|
||||
|
@ -56,6 +56,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'live',
|
||||
'release': '20151203.t.0',
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': None},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -104,6 +105,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'live',
|
||||
'release': '20151203.t.0',
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': None},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -149,6 +151,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'live',
|
||||
'release': '20151203.t.0',
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': None},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -196,6 +199,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'live',
|
||||
'release': None,
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': None},
|
||||
compose.variants['Client'],
|
||||
'amd64')),
|
||||
@ -216,6 +220,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'live',
|
||||
'release': None,
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': None},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -264,6 +269,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'appliance',
|
||||
'release': None,
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': 'https://git.example.com/kickstarts.git?#CAFEBABE'},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -316,6 +322,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'appliance',
|
||||
'release': '20151203.t.0',
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': 'https://git.example.com/kickstarts.git?#CAFEBABE'},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -368,6 +375,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'appliance',
|
||||
'release': '20151203.t.0',
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': 'https://git.example.com/kickstarts.git?#CAFEBABE'},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -415,6 +423,7 @@ class TestLiveImagesPhase(PungiTestCase):
|
||||
'type': 'live',
|
||||
'release': '20151203.t.0',
|
||||
'subvariant': 'Client',
|
||||
'failable_arches': [],
|
||||
'ksurl': None},
|
||||
compose.variants['Client'],
|
||||
'amd64'))])
|
||||
@ -665,10 +674,7 @@ class TestCreateLiveImageThread(PungiTestCase):
|
||||
@mock.patch('pungi.phases.live_images.run')
|
||||
@mock.patch('pungi.phases.live_images.KojiWrapper')
|
||||
def test_process_handles_fail(self, KojiWrapper, run, copy2):
|
||||
compose = DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'failable_deliverables': [('^.+$', {'*': ['live']})],
|
||||
})
|
||||
compose = DummyCompose(self.topdir, {'koji_profile': 'koji'})
|
||||
pool = mock.Mock()
|
||||
cmd = {
|
||||
'ks_file': '/path/to/ks_file',
|
||||
@ -687,6 +693,7 @@ class TestCreateLiveImageThread(PungiTestCase):
|
||||
'subvariant': 'Client',
|
||||
'release': 'xyz',
|
||||
'type': 'live',
|
||||
'failable_arches': ['*'],
|
||||
}
|
||||
|
||||
koji_wrapper = KojiWrapper.return_value
|
||||
@ -711,10 +718,7 @@ class TestCreateLiveImageThread(PungiTestCase):
|
||||
@mock.patch('pungi.phases.live_images.run')
|
||||
@mock.patch('pungi.phases.live_images.KojiWrapper')
|
||||
def test_process_handles_exception(self, KojiWrapper, run, copy2):
|
||||
compose = DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'failable_deliverables': [('^.+$', {'*': ['live']})],
|
||||
})
|
||||
compose = DummyCompose(self.topdir, {'koji_profile': 'koji'})
|
||||
pool = mock.Mock()
|
||||
cmd = {
|
||||
'ks_file': '/path/to/ks_file',
|
||||
@ -733,6 +737,7 @@ class TestCreateLiveImageThread(PungiTestCase):
|
||||
'subvariant': 'Client',
|
||||
'release': 'xyz',
|
||||
'type': 'live',
|
||||
'failable_arches': ['*'],
|
||||
}
|
||||
|
||||
koji_wrapper = KojiWrapper.return_value
|
||||
|
@ -73,6 +73,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
}))])
|
||||
|
||||
@mock.patch('pungi.util.resolve_git_url')
|
||||
@ -133,6 +134,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
})),
|
||||
mock.call((compose,
|
||||
compose.variants['Server'],
|
||||
@ -151,6 +153,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
})),
|
||||
mock.call((compose,
|
||||
compose.variants['Server'],
|
||||
@ -169,6 +172,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': '25',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
}))])
|
||||
|
||||
@mock.patch('pungi.util.resolve_git_url')
|
||||
@ -229,6 +233,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
})),
|
||||
mock.call((compose,
|
||||
compose.variants['Server'],
|
||||
@ -247,6 +252,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
})),
|
||||
mock.call((compose,
|
||||
compose.variants['Server'],
|
||||
@ -265,6 +271,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Server/$basearch/os',
|
||||
'version': '25',
|
||||
'subvariant': 'Server',
|
||||
'failable_arches': [],
|
||||
}))])
|
||||
|
||||
@mock.patch('pungi.phases.livemedia_phase.ThreadPool')
|
||||
@ -335,6 +342,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'version': 'Rawhide',
|
||||
'install_tree_from': 'Everything',
|
||||
'subvariant': 'Something',
|
||||
'failable': ['*'],
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -366,6 +374,7 @@ class TestLiveMediaPhase(PungiTestCase):
|
||||
'install_tree': self.topdir + '/compose/Everything/$basearch/os',
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'Something',
|
||||
'failable_arches': ['*'],
|
||||
}))])
|
||||
|
||||
|
||||
@ -393,6 +402,7 @@ class TestLiveMediaThread(PungiTestCase):
|
||||
'title': None,
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'KDE',
|
||||
'failable_arches': [],
|
||||
}
|
||||
pool = mock.Mock()
|
||||
|
||||
@ -479,9 +489,6 @@ class TestLiveMediaThread(PungiTestCase):
|
||||
def test_handle_koji_fail(self, KojiWrapper, get_file_size, get_mtime):
|
||||
compose = DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'failable_deliverables': [
|
||||
('^.+$', {'*': ['live-media']})
|
||||
]
|
||||
})
|
||||
config = {
|
||||
'arches': ['amd64', 'x86_64'],
|
||||
@ -497,6 +504,7 @@ class TestLiveMediaThread(PungiTestCase):
|
||||
'title': None,
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'KDE',
|
||||
'failable_arches': ['*'],
|
||||
}
|
||||
pool = mock.Mock()
|
||||
|
||||
@ -543,6 +551,7 @@ class TestLiveMediaThread(PungiTestCase):
|
||||
'title': None,
|
||||
'version': 'Rawhide',
|
||||
'subvariant': 'KDE',
|
||||
'failable_arches': ['*'],
|
||||
}
|
||||
pool = mock.Mock()
|
||||
|
||||
|
@ -231,6 +231,21 @@ class OSBSThreadTest(helpers.PungiTestCase):
|
||||
self._assertCorrectCalls({})
|
||||
self._assertCorrectMetadata()
|
||||
|
||||
@mock.patch('pungi.util.resolve_git_url')
|
||||
@mock.patch('pungi.phases.osbs.kojiwrapper.KojiWrapper')
|
||||
def test_run_failable(self, KojiWrapper, resolve_git_url):
|
||||
cfg = {
|
||||
'url': 'git://example.com/repo?#HEAD',
|
||||
'target': 'f24-docker-candidate',
|
||||
'failable': ['*']
|
||||
}
|
||||
self._setupMock(KojiWrapper, resolve_git_url)
|
||||
|
||||
self.t.process((self.compose, self.compose.variants['Server'], cfg), 1)
|
||||
|
||||
self._assertCorrectCalls({})
|
||||
self._assertCorrectMetadata()
|
||||
|
||||
@mock.patch('pungi.util.resolve_git_url')
|
||||
@mock.patch('pungi.phases.osbs.kojiwrapper.KojiWrapper')
|
||||
def test_run_with_more_args(self, KojiWrapper, resolve_git_url):
|
||||
@ -296,10 +311,10 @@ class OSBSThreadTest(helpers.PungiTestCase):
|
||||
cfg = {
|
||||
'url': 'git://example.com/repo?#HEAD',
|
||||
'target': 'fedora-24-docker-candidate',
|
||||
'failable': ['*']
|
||||
}
|
||||
self._setupMock(KojiWrapper, resolve_git_url)
|
||||
self.wrapper.watch_task.return_value = 1
|
||||
self.compose.conf['failable_deliverables'] = [('.*', {'*': ['osbs']})]
|
||||
|
||||
self.t.process((self.compose, self.compose.variants['Server'], cfg), 1)
|
||||
|
||||
|
@ -432,14 +432,12 @@ class OstreeThreadTest(helpers.PungiTestCase):
|
||||
'release_version': 'Rawhide',
|
||||
'koji_profile': 'koji',
|
||||
'runroot_tag': 'rrt',
|
||||
'failable_deliverables': [
|
||||
('^.+$', {'*': ['ostree-installer']})
|
||||
],
|
||||
})
|
||||
pool = mock.Mock()
|
||||
cfg = {
|
||||
'source_repo_from': 'Everything',
|
||||
'release': None,
|
||||
'failable': ['x86_64']
|
||||
}
|
||||
koji = KojiWrapper.return_value
|
||||
koji.run_runroot_cmd.side_effect = helpers.boom
|
||||
@ -466,14 +464,12 @@ class OstreeThreadTest(helpers.PungiTestCase):
|
||||
'release_version': 'Rawhide',
|
||||
'koji_profile': 'koji',
|
||||
'runroot_tag': 'rrt',
|
||||
'failable_deliverables': [
|
||||
('^.+$', {'*': ['ostree-installer']})
|
||||
],
|
||||
})
|
||||
pool = mock.Mock()
|
||||
cfg = {
|
||||
'source_repo_from': 'Everything',
|
||||
'release': None,
|
||||
'failable': ['*'],
|
||||
}
|
||||
koji = KojiWrapper.return_value
|
||||
koji.run_runroot_cmd.return_value = {
|
||||
|
@ -155,9 +155,6 @@ class OSTreeThreadTest(helpers.PungiTestCase):
|
||||
compose = helpers.DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'runroot_tag': 'rrt',
|
||||
'failable_deliverables': [
|
||||
('^.*$', {'*': ['ostree']})
|
||||
]
|
||||
})
|
||||
pool = mock.Mock()
|
||||
cfg = {
|
||||
@ -166,6 +163,7 @@ class OSTreeThreadTest(helpers.PungiTestCase):
|
||||
'config_branch': 'f24',
|
||||
'treefile': 'fedora-atomic-docker-host.json',
|
||||
'ostree_repo': self.repo,
|
||||
'failable': ['*']
|
||||
}
|
||||
koji = KojiWrapper.return_value
|
||||
koji.run_runroot_cmd.return_value = {
|
||||
@ -192,9 +190,6 @@ class OSTreeThreadTest(helpers.PungiTestCase):
|
||||
compose = helpers.DummyCompose(self.topdir, {
|
||||
'koji_profile': 'koji',
|
||||
'runroot_tag': 'rrt',
|
||||
'failable_deliverables': [
|
||||
('^.*$', {'*': ['ostree']})
|
||||
]
|
||||
})
|
||||
pool = mock.Mock()
|
||||
cfg = {
|
||||
@ -203,6 +198,7 @@ class OSTreeThreadTest(helpers.PungiTestCase):
|
||||
'config_branch': 'f24',
|
||||
'treefile': 'fedora-atomic-docker-host.json',
|
||||
'ostree_repo': self.repo,
|
||||
'failable': ['*']
|
||||
}
|
||||
koji = KojiWrapper.return_value
|
||||
koji.run_runroot_cmd.side_effect = helpers.boom
|
||||
|
@ -17,12 +17,6 @@ import pungi.phases.test as test_phase
|
||||
from tests.helpers import DummyCompose, PungiTestCase, touch
|
||||
|
||||
|
||||
FAILABLE_CONFIG = {
|
||||
'failable_deliverables': [
|
||||
('^.+$', {'*': ['iso']}),
|
||||
]
|
||||
}
|
||||
|
||||
PAD = '\0' * 100
|
||||
UNBOOTABLE_ISO = ('\0' * 0x8001) + 'CD001' + PAD
|
||||
ISO_WITH_MBR = ('\0' * 0x1fe) + '\x55\xAA' + ('\0' * 0x7e01) + 'CD001' + PAD
|
||||
@ -40,8 +34,9 @@ class TestCheckImageSanity(PungiTestCase):
|
||||
test_phase.check_image_sanity(compose)
|
||||
|
||||
def test_missing_file_doesnt_report_if_failable(self):
|
||||
compose = DummyCompose(self.topdir, FAILABLE_CONFIG)
|
||||
compose = DummyCompose(self.topdir, {})
|
||||
compose.image.deliverable = 'iso'
|
||||
compose.image.can_fail = True
|
||||
|
||||
try:
|
||||
test_phase.check_image_sanity(compose)
|
||||
@ -83,10 +78,11 @@ class TestCheckImageSanity(PungiTestCase):
|
||||
str(ctx.exception))
|
||||
|
||||
def test_failable_bootable_iso_without_mbr_gpt_doesnt_raise(self):
|
||||
compose = DummyCompose(self.topdir, FAILABLE_CONFIG)
|
||||
compose = DummyCompose(self.topdir, {})
|
||||
compose.image.format = 'iso'
|
||||
compose.image.bootable = True
|
||||
compose.image.deliverable = 'iso'
|
||||
compose.image.can_fail = True
|
||||
touch(os.path.join(self.topdir, 'compose', compose.image.path), UNBOOTABLE_ISO)
|
||||
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user