Merge #459 Fix building images and live media for addons

This commit is contained in:
Dennis Gilmore 2016-11-15 21:00:50 +00:00
commit d4a78a1553
14 changed files with 46 additions and 23 deletions

View File

@ -366,7 +366,7 @@ def run_compose(compose, create_latest_link=True):
pungi.metadata.write_tree_info(compose, arch, variant) pungi.metadata.write_tree_info(compose, arch, variant)
# write .discinfo and media.repo before ISOs are created # write .discinfo and media.repo before ISOs are created
for variant in compose.get_variants(recursive=True): for variant in compose.get_variants():
if variant.type == "addon" or variant.is_empty: if variant.type == "addon" or variant.is_empty:
continue continue
for arch in variant.arches + ["src"]: for arch in variant.arches + ["src"]:

View File

@ -97,7 +97,11 @@ class Compose(kobo.log.LoggingBase):
kobo.log.LoggingBase.__init__(self, logger) kobo.log.LoggingBase.__init__(self, logger)
# TODO: check if minimal conf values are set # TODO: check if minimal conf values are set
self.conf = conf self.conf = conf
# This is a dict mapping UID to Variant objects. It only contains top
# level variants.
self.variants = {} self.variants = {}
# This is a similar mapping, but contains even nested variants.
self.all_variants = {}
self.topdir = os.path.abspath(topdir) self.topdir = os.path.abspath(topdir)
self.skip_phases = skip_phases or [] self.skip_phases = skip_phases or []
self.just_phases = just_phases or [] self.just_phases = just_phases or []
@ -215,19 +219,23 @@ class Compose(kobo.log.LoggingBase):
parser = VariantsXmlParser(file_obj, tree_arches, tree_variants, logger=self._logger) parser = VariantsXmlParser(file_obj, tree_arches, tree_variants, logger=self._logger)
self.variants = parser.parse() self.variants = parser.parse()
self.all_variants = {}
for variant in self.get_variants():
self.all_variants[variant.uid] = variant
# populate ci_base with variants - needed for layered-products (compose_id) # populate ci_base with variants - needed for layered-products (compose_id)
####FIXME - compose_to_composeinfo is no longer needed and has been ####FIXME - compose_to_composeinfo is no longer needed and has been
#### removed, but I'm not entirely sure what this is needed for #### removed, but I'm not entirely sure what this is needed for
#### or if it is at all #### or if it is at all
self.ci_base = compose_to_composeinfo(self) self.ci_base = compose_to_composeinfo(self)
def get_variants(self, types=None, arch=None, recursive=False): def get_variants(self, types=None, arch=None):
result = [] result = []
types = types or ["variant", "optional", "addon", "layered-product"] types = types or ["variant", "optional", "addon", "layered-product"]
for i in self.variants.itervalues(): for i in self.variants.itervalues():
if i.type in types and (not arch or arch in i.arches): if i.type in types and (not arch or arch in i.arches):
result.append(i) result.append(i)
result.extend(i.get_variants(types=types, arch=arch, recursive=recursive)) result.extend(i.get_variants(types=types, arch=arch))
return sorted(set(result)) return sorted(set(result))
def get_arches(self): def get_arches(self):

View File

@ -65,7 +65,7 @@ class CreateisoPhase(PhaseBase):
deliverables = [] deliverables = []
commands = [] commands = []
for variant in self.compose.get_variants(types=["variant", "layered-product", "optional"], recursive=True): for variant in self.compose.get_variants(types=["variant", "layered-product", "optional"]):
for arch in variant.arches + ["src"]: for arch in variant.arches + ["src"]:
skip_iso = get_arch_variant_data(self.compose.conf, "createiso_skip", arch, variant) skip_iso = get_arch_variant_data(self.compose.conf, "createiso_skip", arch, variant)
if skip_iso == [True]: if skip_iso == [True]:

View File

@ -307,7 +307,7 @@ def gather_wrapper(compose, package_sets, path_prefix):
# write packages (package lists) for all variants # write packages (package lists) for all variants
for arch in compose.get_arches(): for arch in compose.get_arches():
for variant in compose.get_variants(arch=arch, recursive=True): for variant in compose.get_variants(arch=arch):
pkg_map = result[arch][variant.uid] pkg_map = result[arch][variant.uid]
write_packages(compose, arch, variant, pkg_map, path_prefix=path_prefix) write_packages(compose, arch, variant, pkg_map, path_prefix=path_prefix)

View File

@ -31,7 +31,7 @@ class ImageBuildPhase(base.ImageConfigMixin, base.ConfigGuardedPhase):
install_tree_from = image_conf.pop('install_tree_from', variant.uid) install_tree_from = image_conf.pop('install_tree_from', variant.uid)
if '://' in install_tree_from: if '://' in install_tree_from:
return install_tree_from return install_tree_from
install_tree_source = self.compose.variants.get(install_tree_from) install_tree_source = self.compose.all_variants.get(install_tree_from)
if not install_tree_source: if not install_tree_source:
raise RuntimeError( raise RuntimeError(
'There is no variant %s to get install tree from when building image for %s.' 'There is no variant %s to get install tree from when building image for %s.'
@ -56,7 +56,7 @@ class ImageBuildPhase(base.ImageConfigMixin, base.ConfigGuardedPhase):
extras.append(variant.uid) extras.append(variant.uid)
for extra in extras: for extra in extras:
v = self.compose.variants.get(extra) v = self.compose.all_variants.get(extra)
if not v: if not v:
raise RuntimeError( raise RuntimeError(
'There is no variant %s to get repo from when building image for %s.' 'There is no variant %s to get repo from when building image for %s.'

View File

@ -47,7 +47,7 @@ class LiveImagesPhase(base.ImageConfigMixin, base.ConfigGuardedPhase):
def _get_extra_repos(self, arch, variant, extras): def _get_extra_repos(self, arch, variant, extras):
repo = [] repo = []
for extra in extras: for extra in extras:
v = self.compose.variants.get(extra) v = self.compose.all_variants.get(extra)
if not v: if not v:
raise RuntimeError( raise RuntimeError(
'There is no variant %s to get repo from when building live image for %s.' 'There is no variant %s to get repo from when building live image for %s.'
@ -72,7 +72,7 @@ class LiveImagesPhase(base.ImageConfigMixin, base.ConfigGuardedPhase):
symlink_isos_to = self.compose.conf.get("symlink_isos_to") symlink_isos_to = self.compose.conf.get("symlink_isos_to")
commands = [] commands = []
for variant in self.compose.variants.values(): for variant in self.compose.all_variants.values():
for arch in variant.arches + ["src"]: for arch in variant.arches + ["src"]:
for data in get_arch_variant_data(self.compose.conf, self.name, arch, variant): for data in get_arch_variant_data(self.compose.conf, self.name, arch, variant):
subvariant = data.get('subvariant', variant.uid) subvariant = data.get('subvariant', variant.uid)

View File

@ -36,7 +36,7 @@ class LiveMediaPhase(ImageConfigMixin, ConfigGuardedPhase):
extras.append(variant.uid) extras.append(variant.uid)
for extra in extras: for extra in extras:
v = self.compose.variants.get(extra) v = self.compose.all_variants.get(extra)
if not v: if not v:
raise RuntimeError( raise RuntimeError(
'There is no variant %s to get repo from when building live media for %s.' 'There is no variant %s to get repo from when building live media for %s.'
@ -56,7 +56,7 @@ class LiveMediaPhase(ImageConfigMixin, ConfigGuardedPhase):
if 'install_tree_from' in image_conf: if 'install_tree_from' in image_conf:
variant_uid = image_conf['install_tree_from'] variant_uid = image_conf['install_tree_from']
try: try:
variant = self.compose.variants[variant_uid] variant = self.compose.all_variants[variant_uid]
except KeyError: except KeyError:
raise RuntimeError( raise RuntimeError(
'There is no variant %s to get repo from when building live media for %s.' 'There is no variant %s to get repo from when building live media for %s.'

View File

@ -45,7 +45,7 @@ class OSTreeThread(WorkerThread):
(arch, variant.uid, self.num)) (arch, variant.uid, self.num))
repodir = os.path.join(workdir, 'config_repo') repodir = os.path.join(workdir, 'config_repo')
source_variant = compose.variants[config['source_repo_from']] source_variant = compose.all_variants[config['source_repo_from']]
source_repo = translate_path(compose, source_repo = translate_path(compose,
compose.paths.compose.repository('$basearch', compose.paths.compose.repository('$basearch',
source_variant, source_variant,

View File

@ -69,7 +69,7 @@ class OstreeInstallerThread(WorkerThread):
""" """
if '://' in source: if '://' in source:
return source.replace('$arch', arch) return source.replace('$arch', arch)
source_variant = compose.variants[source] source_variant = compose.all_variants[source]
return translate_path( return translate_path(
compose, compose.paths.compose.repository(arch, source_variant, create_dir=False)) compose, compose.paths.compose.repository(arch, source_variant, create_dir=False))

View File

@ -59,6 +59,7 @@ class DummyCompose(object):
'Everything': mock.Mock(uid='Everything', arches=['x86_64', 'amd64'], 'Everything': mock.Mock(uid='Everything', arches=['x86_64', 'amd64'],
type='variant', is_empty=False), type='variant', is_empty=False),
} }
self.all_variants = self.variants.copy()
self.log_info = mock.Mock() self.log_info = mock.Mock()
self.log_error = mock.Mock() self.log_error = mock.Mock()
self.log_debug = mock.Mock() self.log_debug = mock.Mock()
@ -73,8 +74,14 @@ class DummyCompose(object):
self.fail_deliverable = mock.Mock() self.fail_deliverable = mock.Mock()
self.require_deliverable = mock.Mock() self.require_deliverable = mock.Mock()
def get_variants(self, arch=None, types=None, recursive=None): def setup_optional(self):
return [v for v in self.variants.values() if not arch or arch in v.arches] self.all_variants['Server-optional'] = mock.Mock(
uid='Server-optional', arches=['x86_64'], type='optional', is_empty=False,
parent=self.variants['Server'])
self.variants['Server'].variants = {'optional': self.all_variants['Server-optional']}
def get_variants(self, arch=None, types=None):
return [v for v in self.all_variants.values() if not arch or arch in v.arches]
def can_fail(self, variant, arch, deliverable): def can_fail(self, variant, arch, deliverable):
failable = get_arch_variant_data(self.conf, 'failable_deliverables', arch, variant) failable = get_arch_variant_data(self.conf, 'failable_deliverables', arch, variant)

View File

@ -28,6 +28,7 @@ class BuildInstallCompose(DummyCompose):
type='variant', buildinstallpackages=[], type='variant', buildinstallpackages=[],
is_empty=False), is_empty=False),
} }
self.all_variants = self.variants.copy()
class TestBuildinstallPhase(PungiTestCase): class TestBuildinstallPhase(PungiTestCase):

View File

@ -277,13 +277,14 @@ class TestImageBuildPhase(PungiTestCase):
'distro': 'Fedora-20', 'distro': 'Fedora-20',
'disk_size': 3, 'disk_size': 3,
'arches': ['x86_64'], 'arches': ['x86_64'],
'install_tree_from': 'Everything', 'install_tree_from': 'Server-optional',
} }
} }
] ]
}, },
'koji_profile': 'koji', 'koji_profile': 'koji',
}) })
compose.setup_optional()
self.assertEqual(validate(compose.conf), []) self.assertEqual(validate(compose.conf), [])
@ -302,7 +303,7 @@ class TestImageBuildPhase(PungiTestCase):
"format": [('docker', 'tar.xz')], "format": [('docker', 'tar.xz')],
"image_conf": { "image_conf": {
'image-build': { 'image-build': {
'install_tree': self.topdir + '/compose/Everything/$arch/os', 'install_tree': self.topdir + '/compose/Server-optional/$arch/os',
'kickstart': 'fedora-docker-base.ks', 'kickstart': 'fedora-docker-base.ks',
'format': 'docker', 'format': 'docker',
'repo': self.topdir + '/compose/Server/$arch/os', 'repo': self.topdir + '/compose/Server/$arch/os',
@ -340,13 +341,14 @@ class TestImageBuildPhase(PungiTestCase):
'distro': 'Fedora-20', 'distro': 'Fedora-20',
'disk_size': 3, 'disk_size': 3,
'arches': ['x86_64'], 'arches': ['x86_64'],
'repo_from': 'Everything', 'repo_from': ['Everything', 'Server-optional'],
} }
} }
] ]
}, },
'koji_profile': 'koji', 'koji_profile': 'koji',
}) })
compose.setup_optional()
self.assertEqual(validate(compose.conf), []) self.assertEqual(validate(compose.conf), [])
@ -369,6 +371,7 @@ class TestImageBuildPhase(PungiTestCase):
'kickstart': 'fedora-docker-base.ks', 'kickstart': 'fedora-docker-base.ks',
'format': 'docker', 'format': 'docker',
'repo': ','.join([self.topdir + '/compose/Everything/$arch/os', 'repo': ','.join([self.topdir + '/compose/Everything/$arch/os',
self.topdir + '/compose/Server-optional/$arch/os',
self.topdir + '/compose/Server/$arch/os']), self.topdir + '/compose/Server/$arch/os']),
'variant': compose.variants['Server'], 'variant': compose.variants['Server'],
'target': 'f24', 'target': 'f24',

View File

@ -25,12 +25,13 @@ class TestLiveImagesPhase(PungiTestCase):
'amd64': { 'amd64': {
'kickstart': 'test.ks', 'kickstart': 'test.ks',
'additional_repos': ['http://example.com/repo/'], 'additional_repos': ['http://example.com/repo/'],
'repo_from': ['Everything'], 'repo_from': ['Everything', 'Server-optional'],
'release': None, 'release': None,
} }
}) })
], ],
}) })
compose.setup_optional()
self.assertEqual(validate(compose.conf), []) self.assertEqual(validate(compose.conf), [])
@ -49,7 +50,8 @@ class TestLiveImagesPhase(PungiTestCase):
'scratch': False, 'scratch': False,
'repos': [self.topdir + '/compose/Client/amd64/os', 'repos': [self.topdir + '/compose/Client/amd64/os',
'http://example.com/repo/', 'http://example.com/repo/',
self.topdir + '/compose/Everything/amd64/os'], self.topdir + '/compose/Everything/amd64/os',
self.topdir + '/compose/Server-optional/amd64/os'],
'label': '', 'label': '',
'name': None, 'name': None,
'filename': 'image-name', 'filename': 'image-name',

View File

@ -326,18 +326,19 @@ class TestLiveMediaPhase(PungiTestCase):
'scratch': True, 'scratch': True,
'skip_tag': True, 'skip_tag': True,
'title': 'Custom Title', 'title': 'Custom Title',
'repo_from': ['Everything'], 'repo_from': ['Everything', 'Server-optional'],
'repo': ['http://example.com/extra_repo'], 'repo': ['http://example.com/extra_repo'],
'arches': ['x86_64'], 'arches': ['x86_64'],
'ksversion': '24', 'ksversion': '24',
'release': None, 'release': None,
'install_tree_from': 'Everything', 'install_tree_from': 'Server-optional',
'subvariant': 'Something', 'subvariant': 'Something',
'failable': ['*'], 'failable': ['*'],
} }
] ]
} }
}) })
compose.setup_optional()
self.assertEqual(validate(compose.conf), []) self.assertEqual(validate(compose.conf), [])
@ -359,12 +360,13 @@ class TestLiveMediaPhase(PungiTestCase):
'release': '20151203.t.0', 'release': '20151203.t.0',
'repo': ['http://example.com/extra_repo', 'repo': ['http://example.com/extra_repo',
self.topdir + '/compose/Everything/$basearch/os', self.topdir + '/compose/Everything/$basearch/os',
self.topdir + '/compose/Server-optional/$basearch/os',
self.topdir + '/compose/Server/$basearch/os'], self.topdir + '/compose/Server/$basearch/os'],
'scratch': True, 'scratch': True,
'skip_tag': True, 'skip_tag': True,
'target': 'f24', 'target': 'f24',
'title': 'Custom Title', 'title': 'Custom Title',
'install_tree': self.topdir + '/compose/Everything/$basearch/os', 'install_tree': self.topdir + '/compose/Server-optional/$basearch/os',
'version': '25', 'version': '25',
'subvariant': 'Something', 'subvariant': 'Something',
'failable_arches': ['*'], 'failable_arches': ['*'],