From 0ef58ca01d680c74f9776bf593990e8e9cadb98d Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Tue, 31 Jul 2018 09:14:35 -0400
Subject: [PATCH 3/3] Move to using flatpak-module-tools as a library
https://github.com/projectatomic/atomic-reactor/pull/1052
Instead of sharing code cut-and-paste between atomic-reactor and
https://pagure.io/flatpak-module-tools, make atomic-reactor use
flatpak-module-tools as a library for the shared code. This will
prevent the code getting out of sync, and make future maintenance
easier.
The flatpak-module-tools version has major improvements to how
the filesystem tree is postprocessed to make a Flatpak using configuration
options from container.yaml, needing some small adjustments of the
tests here.
---
atomic_reactor/plugins/exit_koji_import.py | 6 +-
atomic_reactor/plugins/exit_koji_promote.py | 6 +-
.../plugins/pre_flatpak_create_dockerfile.py | 152 ++-------
.../plugins/pre_resolve_module_compose.py | 12 +-
.../plugins/prepub_flatpak_create_oci.py | 368 +--------------------
images/dockerhost-builder/Dockerfile | 2 +-
images/privileged-builder/Dockerfile | 2 +-
requirements-flatpak.txt | 1 +
tests/flatpak.py | 17 +-
9 files changed, 57 insertions(+), 509 deletions(-)
diff --git a/atomic_reactor/plugins/exit_koji_import.py b/atomic_reactor/plugins/exit_koji_import.py
index 4b1e1c9..e59b557 100644
--- a/atomic_reactor/plugins/exit_koji_import.py
+++ b/atomic_reactor/plugins/exit_koji_import.py
@@ -24,6 +24,7 @@ from atomic_reactor.plugins.pre_reactor_config import get_openshift_session
try:
from atomic_reactor.plugins.pre_flatpak_create_dockerfile import get_flatpak_source_info
+ from atomic_reactor.plugins.pre_resolve_module_compose import get_compose_info
except ImportError:
# modulemd and/or pdc_client not available
def get_flatpak_source_info(_):
@@ -353,7 +354,10 @@ class KojiImportPlugin(ExitPlugin):
flatpak_source_info = get_flatpak_source_info(self.workflow)
if flatpak_source_info is not None:
- extra['image'].update(flatpak_source_info.koji_metadata())
+ compose_info = get_compose_info(self.workflow)
+ koji_metadata = compose_info.koji_metadata()
+ koji_metadata['flatpak'] = True
+ extra['image'].update(koji_metadata)
koji_task_owner = get_koji_task_owner(self.session, koji_task_id).get('name')
extra['submitter'] = self.session.getLoggedInUser()['name']
diff --git a/atomic_reactor/plugins/exit_koji_promote.py b/atomic_reactor/plugins/exit_koji_promote.py
index da33380..0fe1f47 100644
--- a/atomic_reactor/plugins/exit_koji_promote.py
+++ b/atomic_reactor/plugins/exit_koji_promote.py
@@ -30,6 +30,7 @@ from atomic_reactor.util import get_parent_image_koji_data
try:
from atomic_reactor.plugins.pre_flatpak_create_dockerfile import get_flatpak_source_info
+ from atomic_reactor.plugins.pre_resolve_module_compose import get_compose_info
except ImportError:
# modulemd and/or pdc_client not available
def get_flatpak_source_info(_):
@@ -564,7 +565,10 @@ class KojiPromotePlugin(ExitPlugin):
flatpak_source_info = get_flatpak_source_info(self.workflow)
if flatpak_source_info is not None:
- extra['image'].update(flatpak_source_info.koji_metadata())
+ compose_info = get_compose_info(self.workflow)
+ koji_metadata = compose_info.koji_metadata()
+ koji_metadata['flatpak'] = True
+ extra['image'].update(koji_metadata)
resolve_comp_result = self.workflow.prebuild_results.get(PLUGIN_RESOLVE_COMPOSES_KEY)
if resolve_comp_result:
diff --git a/atomic_reactor/plugins/pre_flatpak_create_dockerfile.py b/atomic_reactor/plugins/pre_flatpak_create_dockerfile.py
index 148be70..a53e0da 100644
--- a/atomic_reactor/plugins/pre_flatpak_create_dockerfile.py
+++ b/atomic_reactor/plugins/pre_flatpak_create_dockerfile.py
@@ -20,6 +20,8 @@ Example configuration:
import os
+from flatpak_module_tools.flatpak_builder import FlatpakSourceInfo, FlatpakBuilder
+
from atomic_reactor.constants import DOCKERFILE_FILENAME, YUM_REPOS_DIR
from atomic_reactor.plugin import PreBuildPlugin
from atomic_reactor.plugins.pre_resolve_module_compose import get_compose_info
@@ -52,67 +54,6 @@ RUN chroot /var/tmp/flatpak-build/ /bin/sh /tmp/cleanup.sh
'''
-class FlatpakSourceInfo(object):
- 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()
-
- # The module for the Flatpak runtime that this app runs against
- @property
- def runtime_module(self):
- assert not self.runtime
- compose = self.compose
-
- dependencies = compose.base_module.mmd.props.dependencies
- # A built module should have its dependencies already expanded
- assert len(dependencies) == 1
-
- for key in dependencies[0].peek_buildrequires().keys():
- try:
- module = compose.modules[key]
- if 'runtime' in module.mmd.peek_profiles():
- return module
- except KeyError:
- pass
-
- raise RuntimeError("Failed to identify runtime module in the buildrequires for {}"
- .format(compose.base_module.name))
-
- # All modules that were build against the Flatpak runtime,
- # and thus were built with prefix=/app. This is primarily the app module
- # but might contain modules shared between multiple flatpaks as well.
- @property
- def app_modules(self):
- runtime_module_name = self.runtime_module.mmd.props.name
-
- def is_app_module(m):
- dependencies = m.mmd.props.dependencies
- return runtime_module_name in dependencies[0].peek_buildrequires()
-
- return [m for m in self.compose.modules.values() if is_app_module(m)]
-
- def koji_metadata(self):
- metadata = self.compose.koji_metadata()
- metadata['flatpak'] = True
-
- return metadata
-
-
WORKSPACE_SOURCE_KEY = 'source_info'
@@ -157,7 +98,12 @@ class FlatpakCreateDockerfilePlugin(PreBuildPlugin):
raise RuntimeError(
"resolve_module_compose must be run before flatpak_create_dockerfile")
- return FlatpakSourceInfo(flatpak_yaml, compose_info)
+ module_spec = split_module_spec(compose_info.source_spec)
+
+ return FlatpakSourceInfo(flatpak_yaml,
+ compose_info.modules,
+ compose_info.base_module,
+ module_spec.profile)
def run(self):
"""
@@ -168,38 +114,18 @@ class FlatpakCreateDockerfilePlugin(PreBuildPlugin):
set_flatpak_source_info(self.workflow, source)
- module_info = source.compose.base_module
-
- # For a runtime, certain information is duplicated between the container.yaml
- # and the modulemd, check that it matches
- if source.runtime:
- flatpak_yaml = source.flatpak_yaml
- flatpak_xmd = module_info.mmd.props.xmd['flatpak']
-
- def check(condition, what):
- if not condition:
- raise RuntimeError(
- "Mismatch for {} betweeen module xmd and container.yaml".format(what))
+ builder = FlatpakBuilder(source, None, None)
- check(flatpak_yaml['branch'] == flatpak_xmd['branch'], "'branch'")
- check(source.profile in flatpak_xmd['runtimes'], 'profile name')
-
- profile_xmd = flatpak_xmd['runtimes'][source.profile]
-
- check(flatpak_yaml['id'] == profile_xmd['id'], "'id'")
- check(flatpak_yaml.get('runtime', None) ==
- profile_xmd.get('runtime', None), "'runtime'")
- check(flatpak_yaml.get('sdk', None) == profile_xmd.get('sdk', None), "'sdk'")
+ builder.precheck()
# Create the dockerfile
+ module_info = source.base_module
+
# We need to enable all the modules other than the platform pseudo-module
- modules_str = ' '.join(sorted(m.mmd.props.name + ':' + m.mmd.props.stream
- for m in source.compose.modules.values()
- if m.mmd.props.name != 'platform'))
+ modules_str = ' '.join(builder.get_enable_modules())
- install_packages = module_info.mmd.peek_profiles()[source.profile].props.rpms.get()
- install_packages_str = ' '.join(install_packages)
+ install_packages_str = ' '.join(builder.get_install_packages())
df_path = os.path.join(self.workflow.builder.df_dir, DOCKERFILE_FILENAME)
with open(df_path, 'w') as fp:
@@ -213,54 +139,16 @@ class FlatpakCreateDockerfilePlugin(PreBuildPlugin):
self.workflow.builder.set_df_path(df_path)
- # For a runtime, we want to make sure that the set of RPMs that is installed
- # into the filesystem is *exactly* the set that is listed in the runtime
- # profile. Requiring the full listed set of RPMs to be listed makes it
- # easier to catch unintentional changes in the package list that might break
- # applications depending on the runtime. It also simplifies the checking we
- # do for application flatpaks, since we can simply look at the runtime
- # modulemd to find out what packages are present in the runtime.
- #
- # For an application, we want to make sure that each RPM that is installed
- # into the filesystem is *either* an RPM that is part of the 'runtime'
- # profile of the base runtime, or from a module that was built with
- # flatpak-rpm-macros in the install root and, thus, prefix=/app.
- #
- # We achieve this by restricting the set of available packages in the dnf
- # configuration to just the ones that we want.
- #
- # The advantage of doing this upfront, rather than just checking after the
- # fact is that this makes sure that when a application is being installed,
- # we don't get a different package to satisfy a dependency than the one
- # in the runtime - e.g. aajohan-comfortaa-fonts to satisfy font(:lang=en)
- # because it's alphabetically first.
-
- if not source.runtime:
- runtime_module = source.runtime_module
- runtime_profile = runtime_module.mmd.peek_profiles()['runtime']
- available_packages = sorted(runtime_profile.props.rpms.get())
-
- for m in source.app_modules:
- # Strip off the '.rpm' suffix from the filename to get something
- # that DNF can parse.
- available_packages.extend(x[:-4] for x in m.rpms)
- else:
- base_module = source.compose.base_module
- runtime_profile = base_module.mmd.peek_profiles()['runtime']
- available_packages = sorted(runtime_profile.props.rpms.get())
-
+ includepkgs = builder.get_includepkgs()
includepkgs_path = os.path.join(self.workflow.builder.df_dir, 'atomic-reactor-includepkgs')
with open(includepkgs_path, 'w') as f:
- f.write('includepkgs = ' + ','.join(available_packages) + '\n')
+ f.write('includepkgs = ' + ','.join(includepkgs) + '\n')
# Create the cleanup script
cleanupscript = os.path.join(self.workflow.builder.df_dir, "cleanup.sh")
with open(cleanupscript, 'w') as f:
- cleanup_commands = source.flatpak_yaml.get('cleanup-commands')
- if cleanup_commands is not None:
- f.write(cleanup_commands.rstrip())
- f.write("\n")
+ f.write(builder.get_cleanup_script())
os.chmod(cleanupscript, 0o0755)
# Add a yum-repository pointing to the compose
@@ -270,9 +158,11 @@ class FlatpakCreateDockerfilePlugin(PreBuildPlugin):
stream=module_info.stream,
version=module_info.version)
+ compose_info = get_compose_info(self.workflow)
+
repo = {
'name': repo_name,
- 'baseurl': source.compose.repo_url,
+ 'baseurl': compose_info.repo_url,
'enabled': 1,
'gpgcheck': 0,
}
@@ -280,4 +170,4 @@ class FlatpakCreateDockerfilePlugin(PreBuildPlugin):
path = os.path.join(YUM_REPOS_DIR, repo_name + '.repo')
self.workflow.files[path] = render_yum_repo(repo, escape_dollars=False)
- override_build_kwarg(self.workflow, 'module_compose_id', source.compose.compose_id)
+ override_build_kwarg(self.workflow, 'module_compose_id', compose_info.compose_id)
diff --git a/atomic_reactor/plugins/pre_resolve_module_compose.py b/atomic_reactor/plugins/pre_resolve_module_compose.py
index 5ce6e29..df5f040 100644
--- a/atomic_reactor/plugins/pre_resolve_module_compose.py
+++ b/atomic_reactor/plugins/pre_resolve_module_compose.py
@@ -23,6 +23,9 @@ Example configuration:
}
"""
+
+from flatpak_module_tools.flatpak_builder import ModuleInfo
+
import gi
try:
gi.require_version('Modulemd', '1.0')
@@ -37,15 +40,6 @@ from atomic_reactor.plugins.pre_reactor_config import (get_pdc_session, get_odcs
get_pdc, get_odcs)
-class ModuleInfo(object):
- def __init__(self, name, stream, version, mmd, rpms):
- self.name = name
- self.stream = stream
- self.version = version
- self.mmd = mmd
- self.rpms = rpms
-
-
class ComposeInfo(object):
def __init__(self, source_spec, compose_id, base_module, modules, repo_url):
self.source_spec = source_spec
diff --git a/atomic_reactor/plugins/prepub_flatpak_create_oci.py b/atomic_reactor/plugins/prepub_flatpak_create_oci.py
index b86e792..d1b6463 100644
--- a/atomic_reactor/plugins/prepub_flatpak_create_oci.py
+++ b/atomic_reactor/plugins/prepub_flatpak_create_oci.py
@@ -10,14 +10,7 @@ pre_flatpak_create_dockerfile, extracts the tree at /var/tmp/flatpak-build
and turns it into a Flatpak application or runtime.
"""
-import os
-from six.moves import configparser
-import re
-import shlex
-import shutil
-import subprocess
-import tarfile
-from textwrap import dedent
+from flatpak_module_tools.flatpak_builder import FlatpakBuilder
from atomic_reactor.constants import IMAGE_TYPE_OCI, IMAGE_TYPE_OCI_TAR
from atomic_reactor.plugin import PrePublishPlugin
@@ -26,99 +19,6 @@ from atomic_reactor.rpm_util import parse_rpm_output
from atomic_reactor.util import get_exported_image_metadata
-# Returns flatpak's name for the current arch
-def get_arch():
- return subprocess.check_output(['flatpak', '--default-arch'],
- universal_newlines=True).strip()
-
-
-# flatpak build-init requires the sdk and runtime to be installed on the
-# build system (so that subsequent build steps can execute things with
-# the SDK). While it isn't impossible to download the runtime image and
-# install the flatpak, that would be a lot of unnecessary complexity
-# since our build step is just unpacking the filesystem we've already
-# created. This is a stub implementation of 'flatpak build-init' that
-# doesn't check for the SDK or use it to set up the build filesystem.
-def build_init(directory, appname, sdk, runtime, runtime_branch, tags=[]):
- if not os.path.isdir(directory):
- os.mkdir(directory)
- with open(os.path.join(directory, "metadata"), "w") as f:
- f.write(dedent("""\
- [Application]
- name={appname}
- runtime={runtime}/{arch}/{runtime_branch}
- sdk={sdk}/{arch}/{runtime_branch}
- """.format(appname=appname,
- sdk=sdk,
- runtime=runtime,
- runtime_branch=runtime_branch,
- arch=get_arch())))
- if tags:
- f.write("tags=" + ";".join(tags) + "\n")
- os.mkdir(os.path.join(directory, "files"))
-
-
-# add_app_prefix('org.gimp', 'gimp, 'gimp.desktop') => org.gimp.desktop
-# add_app_prefix('org.gnome', 'eog, 'eog.desktop') => org.gnome.eog.desktop
-def add_app_prefix(app_id, root, full):
- prefix = app_id
- if prefix.endswith('.' + root):
- prefix = prefix[:-(1 + len(root))]
- return prefix + '.' + full
-
-
-def find_desktop_files(builddir):
- desktopdir = os.path.join(builddir, 'files/share/applications')
- for (dirpath, dirnames, filenames) in os.walk(desktopdir):
- for filename in filenames:
- if filename.endswith('.desktop'):
- yield os.path.join(dirpath, filename)
-
-
-def find_icons(builddir, name):
- icondir = os.path.join(builddir, 'files/share/icons/hicolor')
- for (dirpath, dirnames, filenames) in os.walk(icondir):
- for filename in filenames:
- if filename.startswith(name + '.'):
- yield os.path.join(dirpath, filename)
-
-
-def update_desktop_files(app_id, builddir):
- for full_path in find_desktop_files(builddir):
- cp = configparser.RawConfigParser()
- cp.read([full_path])
- try:
- icon = cp.get('Desktop Entry', 'Icon')
- except configparser.NoOptionError:
- icon = None
-
- # Does it have an icon?
- if icon and not icon.startswith(app_id):
- found_icon = False
-
- # Rename any matching icons
- for icon_file in find_icons(builddir, icon):
- shutil.copy(icon_file,
- os.path.join(os.path.dirname(icon_file),
- add_app_prefix(app_id, icon, os.path.basename(icon_file))))
- found_icon = True
-
- # If we renamed the icon, change the desktop file
- if found_icon:
- subprocess.check_call(['desktop-file-edit',
- '--set-icon',
- add_app_prefix(app_id, icon, icon), full_path])
-
- # Is the desktop file not prefixed with the app id, then prefix it
- basename = os.path.basename(full_path)
- if not basename.startswith(app_id):
- shutil.move(full_path,
- os.path.join(os.path.dirname(full_path),
- add_app_prefix(app_id,
- basename[:-len('.desktop')],
- basename)))
-
-
# This converts the generator provided by the export() operation to a file-like
# object with a read that we can pass to tarfile.
class StreamAdapter(object):
@@ -165,133 +65,11 @@ class FlatpakCreateOciPlugin(PrePublishPlugin):
"""
super(FlatpakCreateOciPlugin, self).__init__(tasker, workflow)
- # Compiles a list of path mapping rules to a simple function that matches
- # against a list of fixed patterns, see below for rule syntax
- def _compile_target_rules(rules):
- ROOT = "var/tmp/flatpak-build"
-
- patterns = []
- for source, target in rules:
- source = re.sub("^ROOT", ROOT, source)
- if source.endswith("/"):
- patterns.append((re.compile(source + "(.*)"), target, False))
- patterns.append((source[:-1], target, True))
- else:
- patterns.append((source, target, True))
-
- def get_target_func(self, path):
- for source, target, is_exact_match in patterns:
- if is_exact_match:
- if source == path:
- return target
- else:
- m = source.match(path)
- if m:
- return os.path.join(target, m.group(1))
-
- return None
-
- return get_target_func
-
- # Rules for mapping paths within the exported filesystem image to their
- # location in the final flatpak filesystem
- #
- # ROOT = /var/tmp/flatpak-build
- # No trailing slash - map a directory itself exactly
- # trailing slash - map a directory and everything inside of it
-
- _get_target_path_runtime = _compile_target_rules([
- # We need to make sure that 'files' is created before 'files/etc',
- # which wouldn't happen if just relied on ROOT/usr/ => files.
- # Instead map ROOT => files and omit ROOT/usr
- ("ROOT", "files"),
- ("ROOT/usr", None),
-
- # We map ROOT/usr => files and ROOT/etc => files/etc. This creates
- # A conflict between ROOT/usr/etc and /ROOT/etc. Just assume there
- # is nothing useful in /ROOT/usr/etc.
- ("ROOT/usr/etc/", None),
-
- ("ROOT/usr/", "files"),
- ("ROOT/etc/", "files/etc")
- ])
-
- _get_target_path_app = _compile_target_rules([
- ("ROOT/app/", "files")
- ])
-
- def _get_target_path(self, export_path):
- if self.source.runtime:
- return self._get_target_path_runtime(export_path)
- else:
- return self._get_target_path_app(export_path)
-
def _export_container(self, container_id):
- outfile = os.path.join(self.workflow.source.workdir, 'filesystem.tar.gz')
- manifestfile = os.path.join(self.workflow.source.workdir, 'flatpak-build.rpm_qf')
-
export_generator = self.tasker.d.export(container_id)
export_stream = StreamAdapter(export_generator)
- out_fileobj = open(outfile, "wb")
- compress_process = subprocess.Popen(['gzip', '-c'],
- stdin=subprocess.PIPE,
- stdout=out_fileobj)
- in_tf = tarfile.open(fileobj=export_stream, mode='r|')
- out_tf = tarfile.open(fileobj=compress_process.stdin, mode='w|')
-
- for member in in_tf:
- if member.name == 'var/tmp/flatpak-build.rpm_qf':
- reader = in_tf.extractfile(member)
- with open(manifestfile, 'wb') as out:
- out.write(reader.read())
- reader.close()
- target_name = self._get_target_path(member.name)
- if target_name is None:
- continue
-
- # Match the ownership/permissions changes done by 'flatpak build-export'.
- # See commit_filter() in:
- # https://github.com/flatpak/flatpak/blob/master/app/flatpak-builtins-build-export.c
- #
- # We'll run build-export anyways in the app case, but in the runtime case we skip
- # flatpak build-export and use ostree directly.
- member.uid = 0
- member.gid = 0
- member.uname = "root"
- member.gname = "root"
-
- if member.isdir():
- member.mode = 0o0755
- elif member.mode & 0o0100:
- member.mode = 0o0755
- else:
- member.mode = 0o0644
-
- member.name = target_name
- if member.islnk():
- # Hard links have full paths within the archive (no leading /)
- link_target = self._get_target_path(member.linkname)
- if link_target is None:
- self.log.debug("Skipping %s, hard link to %s", target_name, link_target)
- continue
- member.linkname = link_target
- out_tf.addfile(member)
- elif member.issym():
- # Symlinks have the literal link target, which will be
- # relative to the chroot and doesn't need rewriting
- out_tf.addfile(member)
- else:
- f = in_tf.extractfile(member)
- out_tf.addfile(member, fileobj=f)
-
- in_tf.close()
- out_tf.close()
- export_stream.close()
- compress_process.stdin.close()
- if compress_process.wait() != 0:
- raise RuntimeError("gzip failed")
- out_fileobj.close()
+ outfile, manifestfile = self.builder._export_from_stream(export_stream)
return outfile, manifestfile
@@ -310,148 +88,23 @@ class FlatpakCreateOciPlugin(PrePublishPlugin):
self.log.info("Cleaning up docker container")
self.tasker.d.remove_container(container_id)
- def _get_components(self, manifest):
- with open(manifest, 'r') as f:
- lines = f.readlines()
-
- return parse_rpm_output(lines)
-
- def _filter_app_manifest(self, components):
- runtime_rpms = self.source.runtime_module.mmd.peek_profiles()['runtime'].props.rpms
-
- return [c for c in components if not runtime_rpms.contains(c['name'])]
-
- def _create_runtime_oci(self, tarred_filesystem, outfile):
- info = self.source.flatpak_yaml
-
- builddir = os.path.join(self.workflow.source.workdir, "build")
- os.mkdir(builddir)
-
- repo = os.path.join(self.workflow.source.workdir, "repo")
- subprocess.check_call(['ostree', 'init', '--mode=archive-z2', '--repo', repo])
-
- id_ = info['id']
- runtime_id = info.get('runtime', id_)
- sdk_id = info.get('sdk', id_)
- branch = info['branch']
-
- args = {
- 'id': id_,
- 'runtime_id': runtime_id,
- 'sdk_id': sdk_id,
- 'arch': get_arch(),
- 'branch': branch
- }
-
- METADATA_TEMPLATE = dedent("""\
- [Runtime]
- name={id}
- runtime={runtime_id}/{arch}/{branch}
- sdk={sdk_id}/{arch}/{branch}
-
- [Environment]
- LD_LIBRARY_PATH=/app/lib64:/app/lib
- GI_TYPELIB_PATH=/app/lib64/girepository-1.0
- """)
-
- with open(os.path.join(builddir, 'metadata'), 'w') as f:
- f.write(METADATA_TEMPLATE.format(**args))
-
- runtime_ref = 'runtime/{id}/{arch}/{branch}'.format(**args)
-
- subprocess.check_call(['ostree', 'commit',
- '--repo', repo, '--owner-uid=0',
- '--owner-gid=0', '--no-xattrs',
- '--branch', runtime_ref,
- '-s', 'build of ' + runtime_ref,
- '--tree=tar=' + tarred_filesystem,
- '--tree=dir=' + builddir])
- subprocess.check_call(['ostree', 'summary', '-u', '--repo', repo])
-
- subprocess.check_call(['flatpak', 'build-bundle', repo,
- '--oci', '--runtime',
- outfile, id_, branch])
-
- return runtime_ref
-
- def _find_runtime_info(self):
- runtime_module = self.source.runtime_module
-
- flatpak_xmd = runtime_module.mmd.props.xmd['flatpak']
- runtime_id = flatpak_xmd['runtimes']['runtime']['id']
- sdk_id = flatpak_xmd['runtimes']['runtime'].get('sdk', runtime_id)
- runtime_version = flatpak_xmd['branch']
-
- return runtime_id, sdk_id, runtime_version
-
- def _create_app_oci(self, tarred_filesystem, outfile):
- info = self.source.flatpak_yaml
- app_id = info['id']
- app_branch = info.get('branch', 'master')
-
- builddir = os.path.join(self.workflow.source.workdir, "build")
- os.mkdir(builddir)
-
- repo = os.path.join(self.workflow.source.workdir, "repo")
-
- runtime_id, sdk_id, runtime_version = self._find_runtime_info()
-
- # See comment for build_init() for why we can't use 'flatpak build-init'
- # subprocess.check_call(['flatpak', 'build-init',
- # builddir, app_id, runtime_id, runtime_id, runtime_version])
- build_init(builddir, app_id, sdk_id, runtime_id, runtime_version, tags=info.get('tags', []))
-
- # with gzip'ed tarball, tar is several seconds faster than tarfile.extractall
- subprocess.check_call(['tar', 'xCfz', builddir, tarred_filesystem])
-
- update_desktop_files(app_id, builddir)
-
- finish_args = []
- if 'finish-args' in info:
- # shlex.split(None) reads from standard input, so avoid that
- finish_args = shlex.split(info['finish-args'] or '')
- if 'command' in info:
- finish_args = ['--command', info['command']] + finish_args
-
- subprocess.check_call(['flatpak', 'build-finish'] + finish_args + [builddir])
- subprocess.check_call(['flatpak', 'build-export', repo, builddir, app_branch])
-
- subprocess.check_call(['flatpak', 'build-bundle', repo, '--oci',
- outfile, app_id, app_branch])
-
- app_ref = 'app/{app_id}/{arch}/{branch}'.format(app_id=app_id,
- arch=get_arch(),
- branch=app_branch)
-
- return app_ref
-
def run(self):
self.source = get_flatpak_source_info(self.workflow)
if self.source is None:
raise RuntimeError("flatpak_create_dockerfile must be run before flatpak_create_oci")
+ self.builder = FlatpakBuilder(self.source, self.workflow.source.workdir,
+ 'var/tmp/flatpak-build',
+ parse_manifest=parse_rpm_output)
+
tarred_filesystem, manifest = self._export_filesystem()
self.log.info('filesystem tarfile written to %s', tarred_filesystem)
self.log.info('manifest written to %s', manifest)
- all_components = self._get_components(manifest)
- if self.source.runtime:
- image_components = all_components
- else:
- image_components = self._filter_app_manifest(all_components)
-
- self.log.info("Components:\n%s",
- "\n".join(" {name}-{epoch}:{version}-{release}.{arch}.rpm"
- .format(**c) for c in image_components))
-
+ image_components = self.builder.get_components(manifest)
self.workflow.image_components = image_components
- outfile = os.path.join(self.workflow.source.workdir, 'flatpak-oci-image')
-
- if self.source.runtime:
- ref_name = self._create_runtime_oci(tarred_filesystem, outfile)
- else:
- ref_name = self._create_app_oci(tarred_filesystem, outfile)
+ ref_name, outfile, tarred_outfile = self.builder.build_container(tarred_filesystem)
metadata = get_exported_image_metadata(outfile, IMAGE_TYPE_OCI)
metadata['ref_name'] = ref_name
@@ -459,11 +112,6 @@ class FlatpakCreateOciPlugin(PrePublishPlugin):
self.log.info('OCI image is available as %s', outfile)
- tarred_outfile = outfile + '.tar'
- with tarfile.TarFile(tarred_outfile, "w") as tf:
- for f in os.listdir(outfile):
- tf.add(os.path.join(outfile, f), f)
-
metadata = get_exported_image_metadata(tarred_outfile, IMAGE_TYPE_OCI_TAR)
metadata['ref_name'] = ref_name
self.workflow.exported_image_sequence.append(metadata)
diff --git a/images/dockerhost-builder/Dockerfile b/images/dockerhost-builder/Dockerfile
index 11368b9..7e5be3e 100644
--- a/images/dockerhost-builder/Dockerfile
+++ b/images/dockerhost-builder/Dockerfile
@@ -1,5 +1,5 @@
FROM fedora:latest
-RUN dnf -y install docker git python-docker-py python-setuptools desktop-file-utils e2fsprogs flatpak koji libmodulemd ostree python2-gobject-base python-backports-lzma osbs gssproxy && dnf clean all
+RUN dnf -y install docker git python-docker-py python-setuptools desktop-file-utils e2fsprogs flatpak koji libmodulemd ostree python2-gobject-base python2-flatpak-module-tools python-backports-lzma osbs gssproxy && dnf clean all
ADD ./atomic-reactor.tar.gz /tmp/
RUN cd /tmp/atomic-reactor-*/ && python setup.py install
CMD ["atomic-reactor", "--verbose", "inside-build"]
diff --git a/images/privileged-builder/Dockerfile b/images/privileged-builder/Dockerfile
index a6fa7fd..75653bf 100644
--- a/images/privileged-builder/Dockerfile
+++ b/images/privileged-builder/Dockerfile
@@ -1,5 +1,5 @@
FROM fedora:latest
-RUN dnf -y install docker git python-docker-py python-setuptools desktop-file-utils e2fsprogs flatpak koji libmodulemd ostree python2-gobject-base python-backports-lzma osbs gssproxy && dnf clean all
+RUN dnf -y install docker git python-docker-py python-setuptools desktop-file-utils e2fsprogs flatpak koji libmodulemd ostree python2-gobject-base python2-flatpak-module-tools python-backports-lzma osbs gssproxy && dnf clean all
ADD ./atomic-reactor.tar.gz /tmp/
RUN cd /tmp/atomic-reactor-*/ && python setup.py install
ADD ./docker.sh /tmp/docker.sh
diff --git a/requirements-flatpak.txt b/requirements-flatpak.txt
index a751b49..acb27ca 100644
--- a/requirements-flatpak.txt
+++ b/requirements-flatpak.txt
@@ -1 +1,2 @@
+flatpak-module-tools
pdc-client
diff --git a/tests/flatpak.py b/tests/flatpak.py
index 2ac42e9..c412284 100644
--- a/tests/flatpak.py
+++ b/tests/flatpak.py
@@ -1,11 +1,12 @@
import yaml
+from atomic_reactor.util import split_module_spec
+
try:
- from atomic_reactor.plugins.pre_resolve_module_compose import (ModuleInfo,
- ComposeInfo,
+ from atomic_reactor.plugins.pre_resolve_module_compose import (ComposeInfo,
set_compose_info)
- from atomic_reactor.plugins.pre_flatpak_create_dockerfile import (FlatpakSourceInfo,
- set_flatpak_source_info)
+ from atomic_reactor.plugins.pre_flatpak_create_dockerfile import set_flatpak_source_info
+ from flatpak_module_tools.flatpak_builder import FlatpakSourceInfo, ModuleInfo
from gi.repository import Modulemd
MODULEMD_AVAILABLE = True
except ImportError:
@@ -123,6 +124,9 @@ flatpak:
# Test overriding the automatic "first executable in /usr/bin'
command: eog2
tags: ["Viewer"]
+ copy-icon: true
+ rename-desktop-file: eog.desktop
+ rename-icon: eog
finish-args: >
""" + "".join(" {}\n".format(a) for a in FLATPAK_APP_FINISH_ARGS)
@@ -342,7 +346,10 @@ def setup_flatpak_source_info(workflow, config=APP_CONFIG):
flatpak_yaml = yaml.safe_load(config['container_yaml'])['flatpak']
- source = FlatpakSourceInfo(flatpak_yaml, compose)
+ 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
--
2.14.3