gather: Use another variant as lookaside
Create a temporary repository and add it as another lookaside in the compose. JIRA: COMPOSE-2426 Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
This commit is contained in:
		
							parent
							
								
									ea0964eeef
								
							
						
					
					
						commit
						eaf58f7d40
					
				| @ -179,6 +179,17 @@ class WorkPaths(object): | |||||||
|             makedirs(path) |             makedirs(path) | ||||||
|         return path |         return path | ||||||
| 
 | 
 | ||||||
|  |     def lookaside_repo(self, arch, variant, create_dir=True): | ||||||
|  |         """ | ||||||
|  |         Examples: | ||||||
|  |             work/x86_64/Server/lookaside_repo | ||||||
|  |         """ | ||||||
|  |         path = os.path.join(self.topdir(arch, create_dir=create_dir), | ||||||
|  |                             variant.uid, "lookaside_repo") | ||||||
|  |         if create_dir: | ||||||
|  |             makedirs(path) | ||||||
|  |         return path | ||||||
|  | 
 | ||||||
|     def package_list(self, arch=None, variant=None, pkg_type=None, create_dir=True): |     def package_list(self, arch=None, variant=None, pkg_type=None, create_dir=True): | ||||||
|         """ |         """ | ||||||
|         Examples: |         Examples: | ||||||
| @ -200,6 +211,13 @@ class WorkPaths(object): | |||||||
|         path = os.path.join(path, file_name) |         path = os.path.join(path, file_name) | ||||||
|         return path |         return path | ||||||
| 
 | 
 | ||||||
|  |     def lookaside_package_list(self, arch, variant, create_dir=True): | ||||||
|  |         """ | ||||||
|  |         Examples: | ||||||
|  |             work/x86_64/package_list/Server.x86_64.lookaside.conf | ||||||
|  |         """ | ||||||
|  |         return self.package_list(arch, variant, pkg_type='lookaside', create_dir=create_dir) | ||||||
|  | 
 | ||||||
|     def pungi_download_dir(self, arch, create_dir=True): |     def pungi_download_dir(self, arch, create_dir=True): | ||||||
|         """ |         """ | ||||||
|         Examples: |         Examples: | ||||||
|  | |||||||
| @ -19,16 +19,20 @@ import os | |||||||
| import shutil | import shutil | ||||||
| 
 | 
 | ||||||
| from kobo.rpmlib import parse_nvra | from kobo.rpmlib import parse_nvra | ||||||
|  | from kobo.shortcuts import run | ||||||
| from productmd.rpms import Rpms | from productmd.rpms import Rpms | ||||||
| 
 | 
 | ||||||
| from pungi.wrappers.scm import get_file_from_scm | from pungi.wrappers.scm import get_file_from_scm | ||||||
| from .link import link_files | from .link import link_files | ||||||
|  | from ...wrappers.createrepo import CreaterepoWrapper | ||||||
|  | import pungi.wrappers.kojiwrapper | ||||||
| 
 | 
 | ||||||
| from pungi import Modulemd | from pungi import Modulemd | ||||||
| from pungi.arch import get_compatible_arches, split_name_arch | from pungi.arch import get_compatible_arches, split_name_arch | ||||||
| from pungi.graph import SimpleAcyclicOrientedGraph | from pungi.graph import SimpleAcyclicOrientedGraph | ||||||
| from pungi.phases.base import PhaseBase | from pungi.phases.base import PhaseBase | ||||||
| from pungi.util import get_arch_data, get_arch_variant_data, get_variant_data | from pungi.util import (get_arch_data, get_arch_variant_data, get_variant_data, | ||||||
|  |                         makedirs) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_gather_source(name): | def get_gather_source(name): | ||||||
| @ -308,6 +312,77 @@ def _prepare_variant_as_lookaside(compose): | |||||||
|     return list(variant_processing_order) |     return list(variant_processing_order) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def _make_lookaside_repo(compose, variant, arch, pkg_map): | ||||||
|  |     """ | ||||||
|  |     Create variant lookaside repo for given variant and architecture with | ||||||
|  |     packages from the map. If the repo repo already exists, then nothing will | ||||||
|  |     happen. This could happen if multiple variants depend on this one. | ||||||
|  |     """ | ||||||
|  |     repo = compose.paths.work.lookaside_repo(arch, variant, create_dir=False) | ||||||
|  |     if os.path.exists(repo): | ||||||
|  |         # We have already generated this, nothing to do. | ||||||
|  |         return repo | ||||||
|  | 
 | ||||||
|  |     makedirs(repo) | ||||||
|  |     msg = 'Generating lookaside repo from %s.%s' % (variant.uid, arch) | ||||||
|  |     compose.log_info('[BEGIN] %s', msg) | ||||||
|  | 
 | ||||||
|  |     prefixes = { | ||||||
|  |         'repos': lambda: os.path.join(compose.paths.work.topdir( | ||||||
|  |             arch="global"), "download") + "/", | ||||||
|  |         'koji': lambda: pungi.wrappers.kojiwrapper.KojiWrapper( | ||||||
|  |             compose.conf['koji_profile']).koji_module.config.topdir.rstrip("/") + "/" | ||||||
|  |     } | ||||||
|  |     path_prefix = prefixes[compose.conf['pkgset_source']]() | ||||||
|  |     pkglist = compose.paths.work.lookaside_package_list(arch=arch, variant=variant) | ||||||
|  |     with open(pkglist, 'w') as f: | ||||||
|  |         for packages in pkg_map[arch][variant.uid].values(): | ||||||
|  |             for pkg in packages: | ||||||
|  |                 pkg = pkg['path'] | ||||||
|  |                 if path_prefix and pkg.startswith(path_prefix): | ||||||
|  |                     pkg = pkg[len(path_prefix):] | ||||||
|  |                 f.write('%s\n' % pkg) | ||||||
|  | 
 | ||||||
|  |     cr = CreaterepoWrapper(compose.conf['createrepo_c']) | ||||||
|  |     cmd = cr.get_createrepo_cmd(path_prefix, update=True, database=True, skip_stat=True, | ||||||
|  |                                 pkglist=pkglist, | ||||||
|  |                                 outputdir=repo, | ||||||
|  |                                 baseurl="file://%s" % path_prefix, | ||||||
|  |                                 workers=compose.conf["createrepo_num_workers"], | ||||||
|  |                                 update_md_path=compose.paths.work.arch_repo(arch)) | ||||||
|  |     run(cmd, | ||||||
|  |         logfile=compose.paths.log.log_file(arch, "lookaside_repo_%s" % (variant.uid)), | ||||||
|  |         show_cmd=True) | ||||||
|  |     compose.log_info('[DONE ] %s', msg) | ||||||
|  | 
 | ||||||
|  |     return repo | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def _update_config(compose, variant_uid, arch, repo): | ||||||
|  |     """ | ||||||
|  |     Add the variant lookaside repository into the configuration. | ||||||
|  |     """ | ||||||
|  |     lookasides = compose.conf.setdefault('gather_lookaside_repos', []) | ||||||
|  |     lookasides.append(('^%s$' % variant_uid, {arch: repo})) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def _update_lookaside_config(compose, variant, arch, pkg_map): | ||||||
|  |     """ | ||||||
|  |     Make sure lookaside repo for all variants that the given one depends on | ||||||
|  |     exist, and that configuration is updated to use those repos. | ||||||
|  |     """ | ||||||
|  |     for dest, lookaside_variant_uid in compose.conf.get('variant_as_lookaside', []): | ||||||
|  |         lookaside_variant = compose.all_variants[lookaside_variant_uid] | ||||||
|  |         if dest != variant.uid: | ||||||
|  |             continue | ||||||
|  |         if arch not in lookaside_variant.arches: | ||||||
|  |             compose.log_warning('[SKIP] Skipping lookaside from %s for %s.%s due to arch mismatch', | ||||||
|  |                                 lookaside_variant.uid, variant.uid, arch) | ||||||
|  |             continue | ||||||
|  |         repo = _make_lookaside_repo(compose, lookaside_variant, arch, pkg_map) | ||||||
|  |         _update_config(compose, variant.uid, arch, repo) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def _gather_variants(result, compose, variant_type, package_sets, exclude_fulltree=False): | def _gather_variants(result, compose, variant_type, package_sets, exclude_fulltree=False): | ||||||
|     """Run gathering on all arches of all variants of given type. |     """Run gathering on all arches of all variants of given type. | ||||||
| 
 | 
 | ||||||
| @ -330,6 +405,12 @@ def _gather_variants(result, compose, variant_type, package_sets, exclude_fulltr | |||||||
|             if exclude_fulltree: |             if exclude_fulltree: | ||||||
|                 for pkg_name, pkg_arch in get_parent_pkgs(arch, variant, result)["srpm"]: |                 for pkg_name, pkg_arch in get_parent_pkgs(arch, variant, result)["srpm"]: | ||||||
|                     fulltree_excludes.add(pkg_name) |                     fulltree_excludes.add(pkg_name) | ||||||
|  | 
 | ||||||
|  |             # Get lookaside repos for this variant from other variants. Based | ||||||
|  |             # on the ordering we already know that we have the packages from | ||||||
|  |             # there. | ||||||
|  |             _update_lookaside_config(compose, variant, arch, result) | ||||||
|  | 
 | ||||||
|             pkg_map = gather_packages(compose, arch, variant, package_sets, fulltree_excludes=fulltree_excludes) |             pkg_map = gather_packages(compose, arch, variant, package_sets, fulltree_excludes=fulltree_excludes) | ||||||
|             result.setdefault(arch, {})[variant.uid] = pkg_map |             result.setdefault(arch, {})[variant.uid] = pkg_map | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -901,3 +901,176 @@ class TestGetPackagesToGather(helpers.PungiTestCase): | |||||||
| 
 | 
 | ||||||
|         self.assertItemsEqual(packages, ["foo", "pkg", "foo2.x86_64"]) |         self.assertItemsEqual(packages, ["foo", "pkg", "foo2.x86_64"]) | ||||||
|         self.assertItemsEqual(groups, ["core"]) |         self.assertItemsEqual(groups, ["core"]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestUpdateConfig(unittest.TestCase): | ||||||
|  | 
 | ||||||
|  |     def test_add_to_empty(self): | ||||||
|  |         compose = mock.Mock(conf={}) | ||||||
|  |         gather._update_config(compose, 'Server', 'x86_64', '/tmp/foo') | ||||||
|  |         self.assertEqual(compose.conf, | ||||||
|  |                          {'gather_lookaside_repos': [ | ||||||
|  |                              ('^Server$', {'x86_64': '/tmp/foo'}) | ||||||
|  |                          ]}) | ||||||
|  | 
 | ||||||
|  |     def test_add_to_existing(self): | ||||||
|  |         compose = mock.Mock(conf={'gather_lookaside_repos': [ | ||||||
|  |             ('^Server$', {'x86_64': '/tmp/bar'}), | ||||||
|  |         ]}) | ||||||
|  |         gather._update_config(compose, 'Server', 'x86_64', '/tmp/foo') | ||||||
|  |         self.assertEqual(compose.conf, | ||||||
|  |                          {'gather_lookaside_repos': [ | ||||||
|  |                              ('^Server$', {'x86_64': '/tmp/bar'}), | ||||||
|  |                              ('^Server$', {'x86_64': '/tmp/foo'}) | ||||||
|  |                          ]}) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestUpdateLookasideConfig(helpers.PungiTestCase): | ||||||
|  | 
 | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestUpdateLookasideConfig, self).setUp() | ||||||
|  |         self.compose = helpers.DummyCompose(self.topdir, {}) | ||||||
|  |         self.pkg_map = mock.Mock() | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.phases.gather._update_config') | ||||||
|  |     @mock.patch('pungi.phases.gather._make_lookaside_repo') | ||||||
|  |     def test_no_config(self, mock_make_repo, mock_update_config): | ||||||
|  |         gather._update_lookaside_config(self.compose, self.compose.variants['Server'], | ||||||
|  |                                         'x86_64', self.pkg_map) | ||||||
|  |         self.assertEqual(mock_make_repo.call_args_list, []) | ||||||
|  |         self.assertEqual(mock_update_config.call_args_list, []) | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.phases.gather._update_config') | ||||||
|  |     @mock.patch('pungi.phases.gather._make_lookaside_repo') | ||||||
|  |     def test_no_matching_config(self, mock_make_repo, mock_update_config): | ||||||
|  |         self.compose.conf['variant_as_lookaside'] = [('Everything', 'Client')] | ||||||
|  |         gather._update_lookaside_config(self.compose, self.compose.variants['Server'], | ||||||
|  |                                         'x86_64', self.pkg_map) | ||||||
|  |         self.assertEqual(mock_make_repo.call_args_list, []) | ||||||
|  |         self.assertEqual(mock_update_config.call_args_list, []) | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.phases.gather._update_config') | ||||||
|  |     @mock.patch('pungi.phases.gather._make_lookaside_repo') | ||||||
|  |     def test_missing_arch(self, mock_make_repo, mock_update_config): | ||||||
|  |         # Client only has amd64 | ||||||
|  |         self.compose.conf['variant_as_lookaside'] = [('Server', 'Client')] | ||||||
|  |         gather._update_lookaside_config(self.compose, self.compose.variants['Server'], | ||||||
|  |                                         'x86_64', self.pkg_map) | ||||||
|  |         self.assertEqual(len(self.compose.log_warning.call_args_list), 1) | ||||||
|  |         self.assertEqual(mock_make_repo.call_args_list, []) | ||||||
|  |         self.assertEqual(mock_update_config.call_args_list, []) | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.phases.gather._update_config') | ||||||
|  |     @mock.patch('pungi.phases.gather._make_lookaside_repo') | ||||||
|  |     def test_match(self, mock_make_repo, mock_update_config): | ||||||
|  |         self.compose.conf['variant_as_lookaside'] = [('Server', 'Everything')] | ||||||
|  |         gather._update_lookaside_config(self.compose, self.compose.variants['Server'], | ||||||
|  |                                         'x86_64', self.pkg_map) | ||||||
|  |         self.assertEqual(len(self.compose.log_warning.call_args_list), 0) | ||||||
|  |         self.assertEqual(mock_make_repo.call_args_list, | ||||||
|  |                          [mock.call(self.compose, | ||||||
|  |                                     self.compose.variants['Everything'], | ||||||
|  |                                     'x86_64', | ||||||
|  |                                     self.pkg_map)]) | ||||||
|  |         self.assertEqual(mock_update_config.call_args_list, | ||||||
|  |                          [mock.call(self.compose, 'Server', 'x86_64', | ||||||
|  |                                     mock_make_repo.return_value)]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestMakeLookasideRepo(helpers.PungiTestCase): | ||||||
|  | 
 | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestMakeLookasideRepo, self).setUp() | ||||||
|  |         self.compose = helpers.DummyCompose(self.topdir, {}) | ||||||
|  |         self.variant = self.compose.variants['Server'] | ||||||
|  |         self.arch = 'x86_64' | ||||||
|  |         self.repodir = self.compose.paths.work.lookaside_repo(self.arch, self.variant, create_dir=False) | ||||||
|  |         self.pkglist = self.compose.paths.work.lookaside_package_list(self.arch, self.variant) | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.phases.gather.run') | ||||||
|  |     def test_existing_repo(self, mock_run): | ||||||
|  |         helpers.touch(os.path.join(self.repodir, 'repodata', 'primary.xml')) | ||||||
|  |         repopath = gather._make_lookaside_repo(self.compose, self.variant, self.arch, {}) | ||||||
|  |         self.assertEqual(self.repodir, repopath) | ||||||
|  |         self.assertFalse(os.path.exists(self.pkglist)) | ||||||
|  |         self.assertEqual(mock_run.call_args_list, []) | ||||||
|  | 
 | ||||||
|  |     def assertCorrect(self, repopath, path_prefix, MockCR, mock_run): | ||||||
|  |         with open(self.pkglist) as f: | ||||||
|  |             packages = f.read().splitlines() | ||||||
|  |         self.assertItemsEqual(packages, | ||||||
|  |                               ['pkg/pkg-1.0-1.x86_64.rpm', | ||||||
|  |                                'pkg/pkg-debuginfo-1.0-1.x86_64.rpm', | ||||||
|  |                                'pkg/pkg-1.0-1.src.rpm']) | ||||||
|  | 
 | ||||||
|  |         self.assertEqual(self.repodir, repopath) | ||||||
|  |         print(MockCR.return_value.get_createrepo_cmd.call_args_list) | ||||||
|  |         print([mock.call(path_prefix, update=True, database=True, skip_stat=True, | ||||||
|  |                          pkglist=self.pkglist, outputdir=repopath, | ||||||
|  |                          baseurl="file://%s" % path_prefix, workers=3, | ||||||
|  |                          update_md_path=self.compose.paths.work.arch_repo(self.arch))]) | ||||||
|  |         self.assertEqual(MockCR.return_value.get_createrepo_cmd.call_args_list, | ||||||
|  |                          [mock.call(path_prefix, update=True, database=True, skip_stat=True, | ||||||
|  |                                     pkglist=self.pkglist, outputdir=repopath, | ||||||
|  |                                     baseurl="file://%s" % path_prefix, workers=3, | ||||||
|  |                                     update_md_path=self.compose.paths.work.arch_repo(self.arch))]) | ||||||
|  |         self.assertEqual(mock_run.call_args_list, | ||||||
|  |                          [mock.call(MockCR.return_value.get_createrepo_cmd.return_value, | ||||||
|  |                                     logfile=os.path.join( | ||||||
|  |                                         self.topdir, 'logs', self.arch, | ||||||
|  |                                         'lookaside_repo_Server.%s.log' % self.arch), | ||||||
|  |                                     show_cmd=True)]) | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.wrappers.kojiwrapper.KojiWrapper') | ||||||
|  |     @mock.patch('pungi.phases.gather.CreaterepoWrapper') | ||||||
|  |     @mock.patch('pungi.phases.gather.run') | ||||||
|  |     def test_create_repo_koji_pkgset(self, mock_run, MockCR, MockKW): | ||||||
|  |         self.compose.conf.update({ | ||||||
|  |             'pkgset_source': 'koji', | ||||||
|  |             'koji_profile': 'koji', | ||||||
|  |         }) | ||||||
|  | 
 | ||||||
|  |         pkg_map = { | ||||||
|  |             self.arch: { | ||||||
|  |                 self.variant.uid: { | ||||||
|  |                     'rpm': [{'path': '/tmp/packages/pkg/pkg-1.0-1.x86_64.rpm'}], | ||||||
|  |                     'debuginfo': [{'path': '/tmp/packages/pkg/pkg-debuginfo-1.0-1.x86_64.rpm'}], | ||||||
|  |                     'srpm': [{'path': '/tmp/packages/pkg/pkg-1.0-1.src.rpm'}], | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         MockKW.return_value.koji_module.config.topdir = '/tmp/packages' | ||||||
|  | 
 | ||||||
|  |         repopath = gather._make_lookaside_repo(self.compose, self.variant, self.arch, pkg_map) | ||||||
|  | 
 | ||||||
|  |         self.assertCorrect(repopath, '/tmp/packages/', MockCR, mock_run) | ||||||
|  | 
 | ||||||
|  |     @mock.patch('pungi.phases.gather.CreaterepoWrapper') | ||||||
|  |     @mock.patch('pungi.phases.gather.run') | ||||||
|  |     def test_create_repo_repos_pkgset(self, mock_run, MockCR): | ||||||
|  |         self.compose.conf.update({ | ||||||
|  |             'pkgset_source': 'repos', | ||||||
|  |         }) | ||||||
|  | 
 | ||||||
|  |         dl_dir = self.compose.paths.work.topdir('global') | ||||||
|  | 
 | ||||||
|  |         pkg_map = { | ||||||
|  |             self.arch: { | ||||||
|  |                 self.variant.uid: { | ||||||
|  |                     'rpm': [ | ||||||
|  |                         {'path': os.path.join(dl_dir, 'download/pkg/pkg-1.0-1.x86_64.rpm')} | ||||||
|  |                     ], | ||||||
|  |                     'debuginfo': [ | ||||||
|  |                         {'path': os.path.join(dl_dir, 'download/pkg/pkg-debuginfo-1.0-1.x86_64.rpm')} | ||||||
|  |                     ], | ||||||
|  |                     'srpm': [ | ||||||
|  |                         {'path': os.path.join(dl_dir, 'download/pkg/pkg-1.0-1.src.rpm')} | ||||||
|  |                     ], | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         repopath = gather._make_lookaside_repo(self.compose, self.variant, self.arch, pkg_map) | ||||||
|  | 
 | ||||||
|  |         self.assertCorrect(repopath, dl_dir + '/download/', MockCR, mock_run) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user