def test_is_isolated_build(build_json, isolated): flexmock(util).should_receive('get_build_json').and_return(build_json) if isolated is None: with pytest.raises(KeyError): is_isolated_build() else: assert is_isolated_build() == isolated
def should_run(self): """ Check if the plugin should run or skip execution. :return: bool, False if plugin should skip execution """ if not self.is_in_orchestrator(): self.log.warning("%s plugin set to run on worker. Skipping", self.key) return False if not get_omps_config(self.workflow, None): self.log.info("Integration with OMPS is not configured. Skipping") return False if not has_operator_manifest(self.workflow): self.log.info("Not an operator build. Skipping") return False if is_scratch_build(): self.log.info('Scratch build. Skipping') return False if is_rebuild(self.workflow): self.log.info('Autorebuild. Skipping') return False if is_isolated_build(): self.log.info('Isolated build. Skipping') return False return True
def isolated_from_scratch_build(self): """Isolated builds for FROM scratch builds are prohibited except operator bundle images""" if (self.workflow.data.dockerfile_images.base_from_scratch and is_isolated_build(self.workflow) and not has_operator_bundle_manifest(self.workflow)): raise RuntimeError('"FROM scratch" image build cannot be isolated ' '(except operator bundle images)')
def run(self): """ run the plugin """ if self.koji_target: koji_session = get_koji_session(self.workflow, NO_FALLBACK) self.log.info("Checking koji target for platforms") event_id = koji_session.getLastEvent()['id'] target_info = koji_session.getBuildTarget(self.koji_target, event=event_id) build_tag = target_info['build_tag'] koji_build_conf = koji_session.getBuildConfig(build_tag, event=event_id) koji_platforms = koji_build_conf['arches'] if not koji_platforms: self.log.info("No platforms found in koji target") return None platforms = koji_platforms.split() self.log.info("Koji platforms are %s", sorted(platforms)) if is_scratch_build() or is_isolated_build(): override_platforms = get_orchestrator_platforms(self.workflow) if override_platforms and set(override_platforms) != set( platforms): sort_platforms = sorted(override_platforms) self.log.info("Received user specified platforms %s", sort_platforms) self.log.info("Using them instead of koji platforms") # platforms from user params do not match platforms from koji target # that almost certainly means they were overridden and should be used return set(override_platforms) else: platforms = get_orchestrator_platforms(self.workflow) self.log.info("No koji platforms. User specified platforms are %s", sorted(platforms)) if not platforms: raise RuntimeError( "Cannot determine platforms; no koji target or platform list") # Filter platforms based on clusters enabled_platforms = [] for p in platforms: if self.reactor_config.get_enabled_clusters_for_platform(p): enabled_platforms.append(p) else: self.log.warning( "No cluster found for platform '%s' in reactor config map, skipping", p) final_platforms = get_platforms_in_limits(self.workflow, enabled_platforms) self.log.info("platforms in limits : %s", final_platforms) return final_platforms
def allow_inheritance(self): """Returns boolean if composes can be inherited""" if not self.workflow.source.config.inherit: return False self.log.info("Inheritance requested in config file") if is_scratch_build() or is_isolated_build(): self.log.warning( "Inheritance is not allowed for scratch or isolated builds. " "Skipping inheritance.") return False return True
def allow_inheritance(self): """Returns boolean if composes can be inherited""" if not self.workflow.source.config.inherit: return False self.log.info("Inheritance requested in container.yaml file") if is_scratch_build(self.workflow) or is_isolated_build(self.workflow): msg = ("'inherit: true' in the compose section of container.yaml " "is not allowed for scratch or isolated builds. " "Skipping inheritance.") self.log.warning(msg) self.log.user_warning(message=msg) return False return True
def run(self): """ run the plugin """ if self.koji_target: koji_session = get_koji_session(self.workflow, NO_FALLBACK) self.log.info("Checking koji target for platforms") event_id = koji_session.getLastEvent()['id'] target_info = koji_session.getBuildTarget(self.koji_target, event=event_id) build_tag = target_info['build_tag'] koji_build_conf = koji_session.getBuildConfig(build_tag, event=event_id) koji_platforms = koji_build_conf['arches'] if not koji_platforms: self.log.info("No platforms found in koji target") return None platforms = koji_platforms.split() self.log.info("Koji platforms are %s", sorted(platforms)) if is_scratch_build() or is_isolated_build(): override_platforms = get_orchestrator_platforms(self.workflow) if override_platforms and set(override_platforms) != set(platforms): sort_platforms = sorted(override_platforms) self.log.info("Received user specified platforms %s", sort_platforms) self.log.info("Using them instead of koji platforms") # platforms from user params do not match platforms from koji target # that almost certainly means they were overridden and should be used return set(override_platforms) else: platforms = get_orchestrator_platforms(self.workflow) self.log.info("No koji platforms. User specified platforms are %s", sorted(platforms)) if not platforms: raise RuntimeError("Cannot determine platforms; no koji target or platform list") # Filter platforms based on clusters enabled_platforms = [] for p in platforms: if self.reactor_config.get_enabled_clusters_for_platform(p): enabled_platforms.append(p) else: self.log.warning( "No cluster found for platform '%s' in reactor config map, skipping", p) final_platforms = get_platforms_in_limits(self.workflow, enabled_platforms) self.log.info("platforms in limits : %s", final_platforms) return final_platforms
def run(self): """ run the plugin """ if is_scratch_build(self.workflow): self.log.info('scratch build, skipping plugin') return False if is_isolated_build(self.workflow): self.log.info('isolated build, skipping plugin') return False if self.workflow.builder.dockerfile_images.base_from_scratch: self.log.info( "Skipping check and set rebuild: unsupported for FROM-scratch images" ) return False if self.workflow.builder.dockerfile_images.custom_base_image: self.log.info( "Skipping check and set rebuild: unsupported for custom base images" ) return False metadata = get_build_json().get("metadata", {}) self.build_labels = metadata.get("labels", {}) buildconfig = self.build_labels["buildconfig"] is_rebuild = self.build_labels.get(self.label_key) == self.label_value self.log.info("This is a rebuild? %s", is_rebuild) if not is_rebuild: # Update the BuildConfig metadata so the next Build # instantiated from it is detected as being an automated # rebuild osbs = get_openshift_session(self.workflow, self.openshift_fallback) new_labels = {self.label_key: self.label_value} osbs.update_labels_on_build_config(buildconfig, new_labels) else: self.pull_latest_commit_if_configured() return is_rebuild
def run(self): """ run the plugin """ koji_session = get_koji_session(self.workflow, NO_FALLBACK) self.log.info("Checking koji target for platforms") event_id = koji_session.getLastEvent()['id'] target_info = koji_session.getBuildTarget(self.koji_target, event=event_id) build_tag = target_info['build_tag'] koji_build_conf = koji_session.getBuildConfig(build_tag, event=event_id) koji_platforms = koji_build_conf['arches'] if not koji_platforms: self.log.info("No platforms found in koji target") return None platforms = koji_platforms.split() if is_scratch_build() or is_isolated_build(): override_platforms = get_orchestrator_platforms(self.workflow) if override_platforms and set(override_platforms) != koji_platforms: # platforms from user params do not match platforms from koji target # that almost certainly means they were overridden and should be used return set(override_platforms) return get_platforms_in_limits(self.workflow, platforms)
def __init__( self, tasker, workflow, odcs_url=None, odcs_insecure=False, odcs_openidc_secret_path=None, odcs_ssl_secret_path=None, koji_target=None, koji_hub=None, koji_ssl_certs_dir=None, signing_intent=None, compose_ids=tuple(), repourls=None, minimum_time_to_expire=MINIMUM_TIME_TO_EXPIRE, ): """ :param tasker: ContainerTasker instance :param workflow: DockerBuildWorkflow instance :param odcs_url: URL of ODCS (On Demand Compose Service) :param odcs_insecure: If True, don't check SSL certificates for `odcs_url` :param odcs_openidc_secret_path: directory to look in for a `token` file :param odcs_ssl_secret_path: directory to look in for `cert` file - a PEM file containing both cert and key :param koji_target: str, contains build tag to be used when requesting compose from "tag" :param koji_hub: str, koji hub (xmlrpc), required if koji_target is used :param koji_ssl_certs_dir: str, path to "cert", and "serverca" used when Koji's identity certificate is not trusted :param signing_intent: override the signing intent from git repo configuration :param compose_ids: use the given compose_ids instead of requesting a new one :param repourls: list of str, URLs to the repo files :param minimum_time_to_expire: int, used in deciding when to extend compose's time to expire in seconds """ super(ResolveComposesPlugin, self).__init__(tasker, workflow) if signing_intent and compose_ids: raise ValueError( 'signing_intent and compose_ids cannot be used at the same time' ) self.signing_intent = signing_intent self.compose_ids = compose_ids self.odcs_fallback = { 'api_url': odcs_url, 'insecure': odcs_insecure, 'auth': { 'ssl_certs_dir': odcs_ssl_secret_path, 'openidc_dir': odcs_openidc_secret_path } } self.koji_target = koji_target self.koji_fallback = { 'hub_url': koji_hub, 'auth': { 'ssl_certs_dir': koji_ssl_certs_dir } } if koji_target: if not get_koji(self.workflow, self.koji_fallback)['hub_url']: raise ValueError( 'koji_hub is required when koji_target is used') self.minimum_time_to_expire = minimum_time_to_expire self._koji_session = None self._odcs_client = None self.odcs_config = None self.compose_config = None self.composes_info = None self._parent_signing_intent = None self.repourls = repourls or [] self.inherit = self.workflow.source.config.inherit self.plugin_result = self.workflow.prebuild_results.get( PLUGIN_KOJI_PARENT_KEY) self.allow_inheritance = self.inherit and not (is_scratch_build() or is_isolated_build()) self.all_compose_ids = list(self.compose_ids)
def run(self) -> Optional[List[str]]: """ run the plugin """ if self.koji_target: koji_session = get_koji_session(self.workflow.conf) self.log.info("Checking koji target for platforms") event_id = koji_session.getLastEvent()['id'] target_info = koji_session.getBuildTarget(self.koji_target, event=event_id) build_tag = target_info['build_tag'] koji_build_conf = koji_session.getBuildConfig(build_tag, event=event_id) koji_platforms = koji_build_conf['arches'] if not koji_platforms: self.log.info("No platforms found in koji target") return None platforms = koji_platforms.split() self.log.info("Koji platforms are %s", sorted(platforms)) if is_scratch_build(self.workflow) or is_isolated_build(self.workflow): override_platforms = set(get_orchestrator_platforms(self.workflow) or []) if override_platforms and override_platforms != set(platforms): sorted_platforms = sorted(override_platforms) self.log.info("Received user specified platforms %s", sorted_platforms) self.log.info("Using them instead of koji platforms") # platforms from user params do not match platforms from koji target # that almost certainly means they were overridden and should be used return sorted_platforms else: platforms = get_orchestrator_platforms(self.workflow) user_platforms = sorted(platforms) if platforms else None self.log.info("No koji platforms. User specified platforms are %s", user_platforms) if not platforms: raise RuntimeError("Cannot determine platforms; no koji target or platform list") # Filter platforms based on configured remote hosts remote_host_pools = self.workflow.conf.remote_hosts.get("pools", {}) enabled_platforms = [] defined_but_disabled = [] def has_enabled_hosts(platform: str) -> bool: platform_hosts = remote_host_pools.get(platform, {}) return any(host_info["enabled"] for host_info in platform_hosts.values()) for p in platforms: if has_enabled_hosts(p): enabled_platforms.append(p) elif p in remote_host_pools: defined_but_disabled.append(p) else: self.log.warning("No remote hosts found for platform '%s' in " "reactor config map, skipping", p) if defined_but_disabled: msg = 'Platforms specified in config map, but have all remote hosts disabled' \ ' {}'.format(defined_but_disabled) raise RuntimeError(msg) final_platforms = self._limit_platforms(enabled_platforms) self.log.info("platforms in limits : %s", final_platforms) if not final_platforms: self.log.error("platforms in limits are empty") raise RuntimeError("No platforms to build for") self.workflow.build_dir.init_build_dirs(final_platforms, self.workflow.source) return final_platforms
def __init__(self, tasker, workflow, odcs_url=None, odcs_insecure=False, odcs_openidc_secret_path=None, odcs_ssl_secret_path=None, koji_target=None, koji_hub=None, koji_ssl_certs_dir=None, signing_intent=None, compose_ids=tuple(), repourls=None, minimum_time_to_expire=MINIMUM_TIME_TO_EXPIRE, ): """ :param tasker: DockerTasker instance :param workflow: DockerBuildWorkflow instance :param odcs_url: URL of ODCS (On Demand Compose Service) :param odcs_insecure: If True, don't check SSL certificates for `odcs_url` :param odcs_openidc_secret_path: directory to look in for a `token` file :param odcs_ssl_secret_path: directory to look in for `cert` file - a PEM file containing both cert and key :param koji_target: str, contains build tag to be used when requesting compose from "tag" :param koji_hub: str, koji hub (xmlrpc), required if koji_target is used :param koji_ssl_certs_dir: str, path to "cert", and "serverca" used when Koji's identity certificate is not trusted :param signing_intent: override the signing intent from git repo configuration :param compose_ids: use the given compose_ids instead of requesting a new one :param repourls: list of str, URLs to the repo files :param minimum_time_to_expire: int, used in deciding when to extend compose's time to expire in seconds """ super(ResolveComposesPlugin, self).__init__(tasker, workflow) if signing_intent and compose_ids: raise ValueError('signing_intent and compose_ids cannot be used at the same time') self.signing_intent = signing_intent self.compose_ids = compose_ids self.odcs_fallback = { 'api_url': odcs_url, 'insecure': odcs_insecure, 'auth': { 'ssl_certs_dir': odcs_ssl_secret_path, 'openidc_dir': odcs_openidc_secret_path } } self.koji_target = koji_target self.koji_fallback = { 'hub_url': koji_hub, 'auth': { 'ssl_certs_dir': koji_ssl_certs_dir } } if koji_target: if not get_koji(self.workflow, self.koji_fallback)['hub_url']: raise ValueError('koji_hub is required when koji_target is used') self.minimum_time_to_expire = minimum_time_to_expire self._koji_session = None self._odcs_client = None self.odcs_config = None self.compose_config = None self.composes_info = None self._parent_signing_intent = None self.repourls = repourls or [] self.inherit = self.workflow.source.config.inherit self.plugin_result = self.workflow.prebuild_results.get(PLUGIN_KOJI_PARENT_KEY) self.allow_inheritance = self.inherit and not (is_scratch_build() or is_isolated_build()) self.all_compose_ids = list(self.compose_ids)