def run_image_task(self, image_build_conf): task_id, image_name = self.build_filesystem(image_build_conf) task = TaskWatcher(self.session, task_id, self.poll_interval) try: task.wait() except BuildCanceledException: self.log.info("Build was canceled, canceling task %s", task_id) try: self.session.cancelTask(task_id) self.log.info('task %s canceled', task_id) except Exception as exc: self.log.info("Exception while canceling a task (ignored): %s", util.exception_message(exc)) if task.failed(): try: # Koji may re-raise the error that caused task to fail task_result = self.session.getTaskResult(task_id) except Exception as exc: task_result = util.exception_message(exc) raise RuntimeError('image task, {}, failed: {}'.format( task_id, task_result)) return task_id, image_name
def run(self): self.set_arguments() args = self.parser.parse_args() logging.captureWarnings(True) if args.verbose: set_logging(level=logging.DEBUG) set_logging_osbs(level=logging.DEBUG) elif args.quiet: set_logging(level=logging.WARNING) set_logging_osbs(level=logging.WARNING) else: set_logging(level=logging.INFO) set_logging_osbs(level=logging.INFO) try: args.func(args) except AttributeError: if hasattr(args, 'func'): raise else: self.parser.print_help() except KeyboardInterrupt: pass except Exception as ex: if args.verbose: raise else: logger.error("exception caught: %s", exception_message(ex))
def build_docker_image(self): """ build docker image :return: BuildResult """ exception_being_handled = False self.builder = InsideBuilder(self.source, self.image) # Make sure exit_runner is defined for finally block exit_runner = None try: self.fs_watcher.start() signal.signal(signal.SIGTERM, self.throw_canceled_build_exception) prebuild_runner = PreBuildPluginsRunner( self.builder.tasker, self, self.prebuild_plugins_conf, plugin_files=self.plugin_files) prepublish_runner = PrePublishPluginsRunner( self.builder.tasker, self, self.prepublish_plugins_conf, plugin_files=self.plugin_files) postbuild_runner = PostBuildPluginsRunner( self.builder.tasker, self, self.postbuild_plugins_conf, plugin_files=self.plugin_files) # time to run pre-build plugins, so they can access cloned repo logger.info("running pre-build plugins") try: prebuild_runner.run() except PluginFailedException as ex: logger.error("one or more prebuild plugins failed: %s", ex) raise except AutoRebuildCanceledException as ex: logger.info(str(ex)) self.autorebuild_canceled = True raise # we are delaying initialization, because prebuild plugin reactor_config # might change build method buildstep_runner = BuildStepPluginsRunner( self.builder.tasker, self, self.buildstep_plugins_conf, plugin_files=self.plugin_files) logger.info("running buildstep plugins") try: self.build_result = buildstep_runner.run() if self.build_result.is_failed(): raise PluginFailedException(self.build_result.fail_reason) except PluginFailedException as ex: self.builder.is_built = False logger.error('buildstep plugin failed: %s', ex) raise self.builder.is_built = True if self.build_result.is_image_available(): self.builder.image_id = self.build_result.image_id # run prepublish plugins try: prepublish_runner.run() except PluginFailedException as ex: logger.error("one or more prepublish plugins failed: %s", ex) raise if self.build_result.is_image_available(): self.built_image_inspect = self.builder.inspect_built_image() history = self.builder.tasker.get_image_history( self.builder.image_id) diff_ids = self.built_image_inspect[INSPECT_ROOTFS][ INSPECT_ROOTFS_LAYERS] # diff_ids is ordered oldest first # history is ordered newest first # We want layer_sizes to be ordered oldest first self.layer_sizes = [{ "diff_id": diff_id, "size": layer['Size'] } for (diff_id, layer) in zip(diff_ids, reversed(history))] try: postbuild_runner.run() except PluginFailedException as ex: logger.error("one or more postbuild plugins failed: %s", ex) raise return self.build_result except Exception as ex: logger.debug("caught exception (%s) so running exit plugins", exception_message(ex)) exception_being_handled = True raise finally: # We need to make sure all exit plugins are executed signal.signal(signal.SIGTERM, lambda *args: None) exit_runner = ExitPluginsRunner(self.builder.tasker, self, self.exit_plugins_conf, keep_going=True, plugin_files=self.plugin_files) try: exit_runner.run(keep_going=True) except PluginFailedException as ex: logger.error("one or more exit plugins failed: %s", ex) # raise exception only in case that there is no previous exception being already # handled to prevent replacing original exceptions (root cause) with exceptions # from exit plugins if not exception_being_handled: raise ex finally: self.source.remove_tmpdir() self.fs_watcher.finish() signal.signal(signal.SIGTERM, signal.SIG_DFL)
def build_docker_image(self) -> None: """ build docker image """ print_version_of_tools() exception_being_handled = False # Make sure exit_runner is defined for finally block exit_runner = None try: self.fs_watcher.start() signal.signal(signal.SIGTERM, self.throw_canceled_build_exception) prebuild_runner = PreBuildPluginsRunner( self, self.plugins.prebuild, plugin_files=self.plugin_files) prepublish_runner = PrePublishPluginsRunner( self, self.plugins.prepublish, plugin_files=self.plugin_files) postbuild_runner = PostBuildPluginsRunner( self, self.plugins.postbuild, plugin_files=self.plugin_files) # time to run pre-build plugins, so they can access cloned repo logger.info("running pre-build plugins") try: prebuild_runner.run() except PluginFailedException as ex: logger.error("one or more prebuild plugins failed: %s", ex) raise # we are delaying initialization, because prebuild plugin reactor_config # might change build method buildstep_runner = BuildStepPluginsRunner( self, self.plugins.buildstep, plugin_files=self.plugin_files) logger.info("running buildstep plugins") try: buildstep_runner.run() except PluginFailedException as ex: logger.error('buildstep plugin failed: %s', ex) raise # run prepublish plugins try: prepublish_runner.run() except PluginFailedException as ex: logger.error("one or more prepublish plugins failed: %s", ex) raise try: postbuild_runner.run() except PluginFailedException as ex: logger.error("one or more postbuild plugins failed: %s", ex) raise except Exception as ex: logger.debug("caught exception (%s) so running exit plugins", exception_message(ex)) exception_being_handled = True raise finally: # We need to make sure all exit plugins are executed signal.signal(signal.SIGTERM, lambda *args: None) exit_runner = ExitPluginsRunner(self, self.plugins.exit, keep_going=True, plugin_files=self.plugin_files) try: exit_runner.run(keep_going=True) except PluginFailedException as ex: logger.error("one or more exit plugins failed: %s", ex) # raise exception only in case that there is no previous exception being already # handled to prevent replacing original exceptions (root cause) with exceptions # from exit plugins if not exception_being_handled: raise ex finally: self.fs_watcher.finish() signal.signal(signal.SIGTERM, signal.SIG_DFL)
def run(self, keep_going=False, buildstep_phase=False): """ run all requested plugins :param keep_going: bool, whether to keep going after unexpected failure (only used for exit plugins) :param buildstep_phase: bool, when True remaining plugins will not be executed after a plugin completes (only used for build-step plugins) """ failed_msgs = [] plugin_successful = False plugin_response = None available_plugins = self.available_plugins for plugin in available_plugins: plugin_successful = False logger.debug("running plugin '%s'", plugin.name) start_time = datetime.datetime.now() plugin_response = None skip_response = False try: plugin_instance = self.create_instance_from_plugin( plugin.plugin_class, plugin.conf) self.save_plugin_timestamp(plugin.plugin_class.key, start_time) plugin_response = plugin_instance.run() plugin_successful = True if buildstep_phase: assert isinstance(plugin_response, BuildResult) if plugin_response.is_failed(): logger.error("Build step plugin %s failed: %s", plugin.plugin_class.key, plugin_response.fail_reason) self.on_plugin_failed(plugin.plugin_class.key, plugin_response.fail_reason) plugin_successful = False self.plugins_results[ plugin.plugin_class.key] = plugin_response break except AutoRebuildCanceledException as ex: # if auto rebuild is canceled, then just reraise # NOTE: We need to catch and reraise explicitly, so that the below except clause # doesn't catch this and make PluginFailedException out of it in the end # (calling methods would then need to parse exception message to see if # AutoRebuildCanceledException was raised here) raise except InappropriateBuildStepError: logger.debug('Build step %s is not appropriate', plugin.plugin_class.key) # don't put None, in results for InappropriateBuildStepError skip_response = True if not buildstep_phase: raise except Exception as ex: msg = "plugin '%s' raised an exception: %s" % ( plugin.plugin_class.key, exception_message(ex)) logger.debug(traceback.format_exc()) if not plugin.is_allowed_to_fail: self.on_plugin_failed(plugin.plugin_class.key, ex) if plugin.is_allowed_to_fail or keep_going: logger.warning(msg) logger.info("error is not fatal, continuing...") if not plugin.is_allowed_to_fail: failed_msgs.append(msg) else: logger.error(msg) raise PluginFailedException(msg) plugin_response = ex try: if start_time: finish_time = datetime.datetime.now() duration = finish_time - start_time seconds = duration.total_seconds() logger.debug("plugin '%s' finished in %ds", plugin.name, seconds) self.save_plugin_duration(plugin.plugin_class.key, seconds) except Exception: logger.exception("failed to save plugin duration") if not skip_response: self.plugins_results[plugin.plugin_class.key] = plugin_response if plugin_successful and buildstep_phase: logger.debug('stopping further execution of plugins ' 'after first successful plugin') break if len(failed_msgs) == 1: raise PluginFailedException(failed_msgs[0]) elif len(failed_msgs) > 1: raise PluginFailedException( "Multiple plugins raised an exception: " + str(failed_msgs)) if not plugin_successful and buildstep_phase and not plugin_response: self.on_plugin_failed("BuildStepPlugin", "No appropriate build step") raise PluginFailedException("No appropriate build step") return self.plugins_results
def run(self, keep_going=False, buildstep_phase=False): """ run all requested plugins :param keep_going: bool, whether to keep going after unexpected failure (only used for exit plugins) :param buildstep_phase: bool, when True remaining plugins will not be executed after a plugin completes (only used for build-step plugins) """ failed_msgs = [] plugin_successful = False plugin_response = None available_plugins = self.available_plugins for plugin in available_plugins: plugin_successful = False plugin_response = None skip_response = False try: plugin_instance = self.create_instance_from_plugin( plugin.plugin_class, plugin.conf) with self._execution_timer(plugin): plugin_response = plugin_instance.run() plugin_successful = True except InappropriateBuildStepError: logger.debug('Build step %s is not appropriate', plugin.plugin_class.key) # don't put None, in results for InappropriateBuildStepError skip_response = True if not buildstep_phase: raise except Exception as ex: msg = "plugin '%s' raised an exception: %s" % ( plugin.plugin_class.key, exception_message(ex)) logger.debug(traceback.format_exc()) if not plugin.is_allowed_to_fail: self.on_plugin_failed(plugin.plugin_class.key, ex) if plugin.is_allowed_to_fail or keep_going: logger.warning(msg) logger.info("error is not fatal, continuing...") if not plugin.is_allowed_to_fail: failed_msgs.append(msg) else: logger.error(msg) raise PluginFailedException(msg) from ex plugin_response = ex if not skip_response: self.plugins_results[plugin.plugin_class.key] = plugin_response if plugin_successful and buildstep_phase: logger.debug('stopping further execution of plugins ' 'after first successful plugin') break if len(failed_msgs) == 1: raise PluginFailedException(failed_msgs[0]) elif len(failed_msgs) > 1: raise PluginFailedException( "Multiple plugins raised an exception: " + str(failed_msgs)) # When a buildstep plugin raises InappropriateBuildStepError, next # buildstep plugin will run. This ensures to fail the build process # if all buildstep plugins are tried and no one succeeds. if not plugin_successful and buildstep_phase and available_plugins: self.on_plugin_failed("BuildStepPlugin", "No appropriate build step") raise PluginFailedException("No appropriate build step") return self.plugins_results