def _resolve_modules(self, compose_source): koji_session = get_koji_session(self.workflow, fallback=NO_FALLBACK) resolved_modules = {} for module in compose_source.strip().split(): module_spec = split_module_spec(module) build, rpm_list = get_koji_module_build(koji_session, module_spec) # The returned RPM list contains source RPMs and RPMs for all # architectures. rpms = [ '{name}-{epochnum}:{version}-{release}.{arch}.rpm'.format( epochnum=rpm['epoch'] or 0, **rpm) for rpm in rpm_list ] objects = Modulemd.objects_from_string( build['extra']['typeinfo']['module']['modulemd_str']) assert len(objects) == 1 mmd = objects[0] assert isinstance(mmd, Modulemd.Module) # Make sure we have a version 2 modulemd file mmd.upgrade() resolved_modules[module_spec.name] = ModuleInfo( module_spec.name, module_spec.stream, module_spec.version, mmd, rpms) return resolved_modules
def _resolve_compose(self): odcs_client = get_odcs_session(self.workflow, self.odcs_fallback) self.read_configs_general() modules = self.data.get('modules', []) if not modules: raise RuntimeError( '"compose" config has no modules, a module is required for Flatpaks' ) source_spec = modules[0] if len(modules) > 1: self.log.info( "compose config contains multiple modules," "using first module %s", source_spec) module = split_module_spec(source_spec) self.log.info( "Resolving module compose for name=%s, stream=%s, version=%s", module.name, module.stream, module.version) noprofile_spec = module.to_str(include_profile=False) if self.compose_ids: if len(self.compose_ids) > 1: self.log.info("Multiple compose_ids, using first compose %d", self.compose_ids[0]) self.compose_id = self.compose_ids[0] if self.compose_id is None: self.compose_id = odcs_client.start_compose( source_type='module', source=noprofile_spec)['id'] compose_info = odcs_client.wait_for_compose(self.compose_id) if compose_info['state_name'] != "done": raise RuntimeError("Compose cannot be retrieved, state='%s'" % compose_info['state_name']) compose_source = compose_info['source'] self.log.info("Resolved list of modules: %s", compose_source) resolved_modules = self._resolve_modules(compose_source) base_module = resolved_modules[module.name] assert base_module.stream == module.stream if module.version is not None: assert base_module.version == module.version return ComposeInfo(source_spec=source_spec, compose_id=self.compose_id, base_module=base_module, modules=resolved_modules, repo_url=compose_info['result_repo'] + '/$basearch/os/')
def setup_flatpak_source_info(workflow, config=APP_CONFIG): compose = setup_flatpak_compose_info(workflow, config) flatpak_yaml = yaml.safe_load(config['container_yaml'])['flatpak'] module_spec = split_module_spec(compose.source_spec) source = FlatpakSourceInfo(flatpak_yaml, compose.modules, compose.base_module, module_spec.profile) set_flatpak_source_info(workflow, source) return source
def _load_source(self): flatpak_yaml = self.workflow.source.config.flatpak compose_info = get_compose_info(self.workflow) if compose_info is None: raise RuntimeError( "resolve_module_compose must be run before flatpak_create_dockerfile" ) module_spec = split_module_spec(compose_info.source_spec) return FlatpakSourceInfo(flatpak_yaml, compose_info.modules, compose_info.base_module, module_spec.profile)
def __init__(self, flatpak_yaml, compose): self.flatpak_yaml = flatpak_yaml self.compose = compose mmd = compose.base_module.mmd # A runtime module must have a 'runtime' profile, but can have other # profiles for SDKs, minimal runtimes, etc. self.runtime = 'runtime' in mmd.peek_profiles() module_spec = split_module_spec(compose.source_spec) if module_spec.profile: self.profile = module_spec.profile elif self.runtime: self.profile = 'runtime' else: self.profile = 'default' assert self.profile in mmd.peek_profiles()
def test_without_context(self, koji_return, should_raise): module = 'eog:master:20180821163756' spec = split_module_spec(module) session = flexmock() (session.should_receive('getPackageID').with_args('eog').and_return( 303)) (session.should_receive('listBuilds').with_args( packageID=303, type='module', state=koji.BUILD_STATES['COMPLETE']).and_return(koji_return)) if should_raise: with pytest.raises(Exception) as e: get_koji_module_build(session, spec) assert should_raise in str(e) else: self.mock_get_rpms(session) get_koji_module_build(session, spec)
def _resolve_modules(self, compose_source): resolved_modules = {} # The effect of develop=True is that requests to the PDC are made without authentication; # since we our interaction with the PDC is read-only, this is fine for our needs and # makes things simpler. pdc_client = get_pdc_session(self.workflow, self.pdc_fallback) for module_spec in compose_source.strip().split(): try: module = split_module_spec(module_spec) if not module.version: raise RuntimeError except RuntimeError: raise RuntimeError("Cannot parse resolved module in compose: %s" % module_spec) query = { 'variant_id': module.name, 'variant_version': module.stream, 'variant_release': module.version, 'active': True, } self.log.info("Looking up module metadata for '%s' in the PDC", module_spec) retval = pdc_client['unreleasedvariants/'](page_size=-1, fields=['modulemd', 'rpms'], **query) # Error handling if not retval: raise RuntimeError("Failed to find module in PDC %r" % query) if len(retval) != 1: raise RuntimeError("Multiple modules in the PDC matched %r" % query) objects = Modulemd.objects_from_string(retval[0]['modulemd']) assert len(objects) == 1 mmd = objects[0] assert isinstance(mmd, Modulemd.Module) # Make sure we have a version 2 modulemd file mmd.upgrade() rpms = set(retval[0]['rpms']) resolved_modules[module.name] = ModuleInfo(module.name, module.stream, module.version, mmd, rpms) return resolved_modules
def test_with_context(self): module = 'eog:master:20180821163756:775baa8e' module_koji_nvr = 'eog-master-20180821163756.775baa8e' koji_return = { 'build_id': 1138198, 'name': 'eog', 'version': 'master', 'release': '20180821163756.775baa8e', 'extra': { 'typeinfo': { 'module': { 'modulemd_str': 'document: modulemd\nversion: 2' } } } } spec = split_module_spec(module) session = flexmock() (session.should_receive('getBuild').with_args( module_koji_nvr).and_return(koji_return)) self.mock_get_rpms(session) get_koji_module_build(session, spec)
def test_module_spec_to_str(as_str, as_str_no_profile): spec = split_module_spec(as_str) assert spec.to_str() == as_str assert spec.to_str(include_profile=False) == as_str_no_profile
def test_split_module_spec(module, should_raise, expected): if should_raise: with pytest.raises(RuntimeError): split_module_spec(module) else: assert split_module_spec(module) == expected