diff --git a/pungi/phases/image_build.py b/pungi/phases/image_build.py index b1d0f878..5cfdbb09 100644 --- a/pungi/phases/image_build.py +++ b/pungi/phases/image_build.py @@ -120,6 +120,12 @@ class ImageBuildPhase(base.PhaseLoggerMixin, base.ImageConfigMixin, base.ConfigG image_conf["image-build"]["format"] = ",".join([x[0] for x in image_conf["image-build"]["format"]]) image_conf["image-build"]['repo'] = self._get_repo(image_conf['image-build'], variant) + can_fail = image_conf['image-build'].pop('failable', []) + if can_fail == ['*']: + can_fail = image_conf['image-build']['arches'] + if can_fail: + image_conf['image-build']['can_fail'] = ','.join(sorted(can_fail)) + cmd = { "format": format, "image_conf": image_conf, @@ -134,7 +140,6 @@ class ImageBuildPhase(base.PhaseLoggerMixin, base.ImageConfigMixin, base.ConfigG ), "link_type": self.compose.conf["link_type"], "scratch": image_conf['image-build'].pop('scratch', False), - "failable_arches": image_conf['image-build'].pop('failable', []), } self.pool.add(CreateImageBuildThread(self.pool)) self.pool.queue_put((self.compose, cmd)) @@ -150,15 +155,15 @@ class CreateImageBuildThread(WorkerThread): compose, cmd = item variant = cmd["image_conf"]["image-build"]["variant"] subvariant = cmd["image_conf"]["image-build"].get("subvariant", variant.uid) - failable_arches = cmd.get('failable_arches', []) - self.can_fail = bool(failable_arches) - # TODO handle failure per architecture; currently not possible in single task + self.failable_arches = cmd["image_conf"]['image-build'].get('can_fail', '') + self.can_fail = self.failable_arches == cmd['image_conf']['image-build']['arches'] with failable(compose, self.can_fail, variant, '*', 'image-build', subvariant, logger=self.pool._logger): self.worker(num, compose, variant, subvariant, cmd) def worker(self, num, compose, variant, subvariant, cmd): arches = cmd["image_conf"]["image-build"]['arches'].split(',') + failable_arches = self.failable_arches.split(',') dash_arches = '-'.join(arches) log_file = compose.paths.log.log_file( dash_arches, @@ -202,7 +207,7 @@ class CreateImageBuildThread(WorkerThread): image_infos.append({'path': path, 'suffix': suffix, 'type': format, 'arch': arch}) break - if len(image_infos) != len(cmd['format']) * len(arches): + if len(image_infos) != len(cmd['format']) * (len(arches) - len(failable_arches)): self.pool.log_error( "Error in koji task %s. Expected to find same amount of images " "as in suffixes attr in image-build (%s) for each arch (%s). Got '%s'." % diff --git a/pungi/wrappers/kojiwrapper.py b/pungi/wrappers/kojiwrapper.py index f75b3f54..7f4ff82e 100644 --- a/pungi/wrappers/kojiwrapper.py +++ b/pungi/wrappers/kojiwrapper.py @@ -190,7 +190,7 @@ class KojiWrapper(object): cmd.append('--release=%s' % options['release']) if 'can_fail' in options: - cmd.append('--can-fail=%s' % options['can_fail']) + cmd.append('--can-fail=%s' % ','.join(options['can_fail'])) if wait: cmd.append('--wait') diff --git a/tests/test_imagebuildphase.py b/tests/test_imagebuildphase.py index 5f753cfd..86012acd 100644 --- a/tests/test_imagebuildphase.py +++ b/tests/test_imagebuildphase.py @@ -70,6 +70,7 @@ class TestImageBuildPhase(PungiTestCase): 'version': 'Rawhide', 'ksurl': 'git://git.fedorahosted.org/git/spin-kickstarts.git', 'distro': 'Fedora-20', + 'can_fail': 'x86_64', } }, "conf_file": self.topdir + '/work/image-build/Client/docker_Fedora-Docker-Base.cfg', @@ -77,7 +78,6 @@ class TestImageBuildPhase(PungiTestCase): "relative_image_dir": 'Client/%(arch)s/images', "link_type": 'hardlink-or-copy', "scratch": False, - "failable_arches": ['x86_64'], } server_args = { "format": [('docker', 'tar.xz')], @@ -95,6 +95,7 @@ class TestImageBuildPhase(PungiTestCase): 'version': 'Rawhide', 'ksurl': 'git://git.fedorahosted.org/git/spin-kickstarts.git', 'distro': 'Fedora-20', + 'can_fail': 'x86_64', } }, "conf_file": self.topdir + '/work/image-build/Server/docker_Fedora-Docker-Base.cfg', @@ -102,7 +103,6 @@ class TestImageBuildPhase(PungiTestCase): "relative_image_dir": 'Server/%(arch)s/images', "link_type": 'hardlink-or-copy', "scratch": False, - "failable_arches": ['x86_64'], } self.assertItemsEqual(phase.pool.queue_put.mock_calls, [mock.call((compose, client_args)), @@ -163,7 +163,6 @@ class TestImageBuildPhase(PungiTestCase): "relative_image_dir": 'Server/%(arch)s/images', "link_type": 'hardlink-or-copy', "scratch": False, - "failable_arches": [], } self.assertItemsEqual(phase.pool.queue_put.mock_calls, [mock.call((compose, server_args))]) @@ -220,7 +219,6 @@ class TestImageBuildPhase(PungiTestCase): "relative_image_dir": 'Server/%(arch)s/images', "link_type": 'hardlink-or-copy', "scratch": False, - "failable_arches": [], } self.assertItemsEqual(phase.pool.queue_put.mock_calls, [mock.call((compose, server_args))]) @@ -318,7 +316,6 @@ 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') @@ -383,7 +380,6 @@ 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') @@ -445,7 +441,6 @@ 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') @@ -612,6 +607,7 @@ class TestImageBuildPhase(PungiTestCase): 'version': 'Rawhide', 'ksurl': 'git://git.fedorahosted.org/git/spin-kickstarts.git', 'distro': 'Fedora-20', + 'can_fail': 'x86_64', } }, "conf_file": self.topdir + '/work/image-build/Server-optional/docker_Fedora-Docker-Base.cfg', @@ -619,7 +615,6 @@ class TestImageBuildPhase(PungiTestCase): "relative_image_dir": 'Server-optional/%(arch)s/images', "link_type": 'hardlink-or-copy', "scratch": False, - "failable_arches": ['x86_64'], } self.assertItemsEqual(phase.pool.queue_put.mock_calls, [mock.call((compose, server_args))]) @@ -781,6 +776,7 @@ class TestCreateImageBuildThread(PungiTestCase): 'version': 'Rawhide', 'ksurl': 'git://git.fedorahosted.org/git/spin-kickstarts.git', 'distro': 'Fedora-20', + "can_fail": 'amd64,x86_64', } }, "conf_file": 'amd64,x86_64-Client-Fedora-Docker-Base-docker', @@ -788,7 +784,6 @@ 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 = { @@ -829,6 +824,7 @@ class TestCreateImageBuildThread(PungiTestCase): 'version': 'Rawhide', 'ksurl': 'git://git.fedorahosted.org/git/spin-kickstarts.git', 'distro': 'Fedora-20', + 'can_fail': 'amd64,x86_64', } }, "conf_file": 'amd64,x86_64-Client-Fedora-Docker-Base-docker', @@ -836,7 +832,6 @@ 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 @@ -851,6 +846,49 @@ class TestCreateImageBuildThread(PungiTestCase): mock.call('BOOM'), ]) + @mock.patch('pungi.phases.image_build.KojiWrapper') + @mock.patch('pungi.phases.image_build.Linker') + def test_process_handle_fail_only_one_optional(self, Linker, KojiWrapper): + compose = DummyCompose(self.topdir, {'koji_profile': 'koji'}) + pool = mock.Mock() + cmd = { + "format": [('docker', 'tar.xz'), ('qcow2', 'qcow2')], + "image_conf": { + 'image-build': { + 'install_tree': '/ostree/$arch/Client', + 'kickstart': 'fedora-docker-base.ks', + 'format': 'docker', + 'repo': '/ostree/$arch/Client', + 'variant': compose.variants['Client'], + 'target': 'f24', + 'disk_size': 3, + 'name': 'Fedora-Docker-Base', + 'arches': 'amd64,x86_64', + 'version': 'Rawhide', + 'ksurl': 'git://git.fedorahosted.org/git/spin-kickstarts.git', + 'distro': 'Fedora-20', + 'can_fail': 'amd64', + } + }, + "conf_file": 'amd64,x86_64-Client-Fedora-Docker-Base-docker', + "image_dir": '/image_dir/Client/%(arch)s', + "relative_image_dir": 'image_dir/Client/%(arch)s', + "link_type": 'hardlink-or-copy', + 'scratch': False, + } + + koji_wrapper = KojiWrapper.return_value + koji_wrapper.run_blocking_cmd.return_value = { + "retcode": 1, + "output": None, + "task_id": 1234, + } + + t = CreateImageBuildThread(pool) + with self.assertRaises(RuntimeError): + with mock.patch('time.sleep'): + t.process((compose, cmd), 1) + if __name__ == "__main__": unittest.main()